/**
* Snippet Detectar variables globales
* en Javascript por Carlos Benítez
*/
(function( context ){
var globals = { viewGlobals : true },
startGlobals = [],
newGlobals = [];
for (var j in window) {
globals[j] = true;
startGlobals.push(j);
}
setInterval(function() {
for ( var j in window ) {
if ( !globals[j] ) {
globals[j] = true;
newGlobals.push(j);
console.warn( 'New Global: ' + j + ' = ' + window[j] + '. Typeof: ' + (typeof window[j]) );
}
}
}, 1000);
context.viewGlobals = function(){
console.groupCollapsed( 'View globals' );
console.groupCollapsed( 'Initial globals' );
console.log( startGlobals.sort().join( ",\n" ) );
console.groupEnd();
console.groupCollapsed( 'New globals' );
console.warn( newGlobals.sort().join( ",\n" ) );
console.groupEnd();
console.groupEnd();
};
})(this);
- Ejemplo (modificado) de Valentín Starck:
function write(t) {
console.log(new Date + ' | ' +t);
}
var Queue = function() {
this._tasks = [];
};
Queue.prototype.add = function(fn, scope) {
this._tasks.push({
fn: fn,
scope: scope
});
return this;
};
Queue.prototype.process = function() {
var proxy, self = this;
task = this._tasks.shift();
if(!task) {
return;
}
proxy = {
end: function() {
self.process();
}
};
task.fn.call(task.scope, proxy);
return this;
};
Queue.prototype.clear = function() {
this._tasks = [];
return this;
};
var q = new Queue();
// Tarea 1 (sincronica)
q.add(function(proxy) {
write('Tarea 1 (sincronica)');
proxy.end();
});
// Tarea 2 (asincronica)
q.add(function(proxy) {
write('Tarea 2 (asincronica)');
setTimeout(function() {
proxy.end();
}, 2500);
});
// Tarea 3 (sincronica)
q.add(function(proxy) {
write('Tarea 3 (sincronica)');
proxy.end();
});
// Tarea 4 (asincronica)
q.add(function(proxy) {
write('Tarea 4 (asincronica)');
setTimeout(function() {
proxy.end();
}, 2500);
});
// Tarea 5 (sincronica)
q.add(function(proxy) {
write('Tarea 5 (sincronica)');
proxy.end();
});
q.process();
- Callback Hell
- Escalabilidad limitada
- Problemas para gestionar errores
- Anidaciones complejas
obj.metodo1(data, function(data1) { function(data1, function(data2) { obj.otroMetodo(data2, function(data3) { obj.otroMetodoMas(data3, function(data4) { // más y más..... }) }) }) })
A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled. From promisesaplus.com/
-
Estados:
- Fulfilled – La acción en relación con la promesa se logró.
- Rejected – La acción en relación con la promesa falló.
- Pending – Pendiente, no se ha cumplido o rechazado aún.
- Settled - Arreglada, se ha cumplido o se ha rechazado (resuelta).
-
En ECMA6:
-
- Una promesa
var cuentaPromesas = 0; var errorMode = false; function testPromesa() { var numPromesaActual = ++cuentaPromesas; console.warn("Promesa Asíncrona numero ("+numPromesaActual+") - Iniciada") var miPromesa = new Promise( function(resolve, reject) { console.info("Promesa Asíncrona numero ("+numPromesaActual+") - Proceso asincrónico empezado"); if(errorMode){ reject(numPromesaActual) } else{ window.setTimeout( function() { resolve(numPromesaActual) }, Math.random() * 2000 + 1000); } }); miPromesa.then( function(val) { console.info("Promesa Asíncrona numero ("+val+") - Proceso asincrónico terminado"); console.warn("Promesa Asíncrona numero ("+numPromesaActual+") - Finalizada"); }).catch( function(val){ console.error("Promesa Asíncrona numero ("+val+") - ERROR FATAL"); }); }; testPromesa();
- Usando .race()
var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "uno"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "dos"); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // "dos" - p2 más rápida });
- Usando .all()
var errorMode = false var p1 = new Promise(function(resolve, reject) { console.log("P1 - Iniciada"); setTimeout(resolve, 1000, "P1 - Terminada"); }); var p2 = new Promise(function(resolve, reject) { console.log("P2 - Iniciada"); setTimeout(resolve, 2000, "P2 - Terminada"); }); var p3 = new Promise(function(resolve, reject) { if(errorMode){ reject("errorMode-Activado"); } else { console.log("P3 - Iniciada"); setTimeout(resolve, 3000, "P3 - Terminada"); } }); var p4 = new Promise(function(resolve, reject) { console.log("P4 - Iniciada"); setTimeout(resolve, 4000, "P4 - Terminada"); }); Promise.all([p1, p2, p3, p4]).then(function(value) { console.info("Promise.all -> TODO TERMINADO", value) }, function(reason) { console.log("Parece... que fallamos!", reason) });
- Usando Ajax
function $http(url){ var core = { ajax : function (method, url, args) { var promise = new Promise( function (resolve, reject) { var client = new XMLHttpRequest(); var uri = url; if (args && (method === 'POST' || method === 'PUT')) { uri += '?'; var argcount = 0; for (var key in args) { if (args.hasOwnProperty(key)) { if (argcount++) { uri += '&'; } uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]); } } } client.open(method, uri); client.send(); client.onload = function () { if (this.status >= 200 && this.status < 300) { resolve(this.response); } else { reject(this.statusText); } }; client.onerror = function () { reject(this.statusText); }; }); return promise; } }; // Patrón Adaptador return { 'get' : function(args) { return core.ajax('GET', url, args); }, 'post' : function(args) { return core.ajax('POST', url, args); }, 'put' : function(args) { return core.ajax('PUT', url, args); }, 'delete' : function(args) { return core.ajax('DELETE', url, args); } }; }; var callback = { success : function(data){ console.log(1, 'success', JSON.parse(data)); }, error : function(data){ console.log(2, 'error', JSON.parse(data)); } }; // Prueba bicis $http("http://bicimad-api.herokuapp.com/api-v1/locations/") .get() .then(callback.success) .catch(callback.error); // Prueba bicis 2 var bicisCerca = { url: 'http://bicimad-api.herokuapp.com/api-v1/locations/nearest/', lat: '40.418889', long: '-3.691944', distance: '1000000000' }; var cercaMio = bicisCerca.url+"?lat="+bicisCerca.lat+"&long="+bicisCerca.long+"&distance="+bicisCerca.distance; $http(cercaMio) .get() .then(callback.success) .catch(callback.error);
-
Alternativas para usar promesas:
-
function primeraFuncion() { var deferred = Q.defer(); setTimeout(function() { console.info('Primera funcion'); deferred.resolve(); }, 2000); return deferred.promise; } function segundaFuncion() { var deferred = Q.defer(); setTimeout(function() { console.info('Segunda funcion'); deferred.resolve(); }, 1000); return deferred.promise; } Q() .then(primeraFuncion) .then(segundaFuncion) .done();
-
Entendiendo la utilidad de Require.js
-
Código convencional (Código espagueti):
- Código espagueti
- index.html:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Testing Requirejs</title> </head> <body> <script src="calculadora.js"></script> </body> </html>
- calculadora.js
function sumar (x, y) { return x+y }; function restar (x, y) { return x-y }; function multiplicar (x, y) { return x*y }; function dividir (x, y) { return x/y };
-
Código convencional (Creando un objeto):
- calculadora.js
var calculadora = {}; calculadora.sumar = function (x,y) { return x + y }; calculadora.restar = function (x, y) { return x - y } calculadora.multiplicar = function (x, y) { return x * y } calculadora.divir = function (x, y) { return x / y }
-
Código convencional (Mejorando la escalabilidad "dividiendo el objeto"):
- index.html:
<script src="sumar.js"></script> <script src="restar.js"></script> <script src="divir.js"></script> <script src="multiplicar.js"></script>
- /sumar.js
var calculadora = calculadora || {}; calculadora.sumar = function (x,y) { return x + y };
- /restar.js
var calculadora = calculadora || {}; calculadora.restar = function (x, y) { return x - y }
- /dividir.js
var calculadora = calculadora || {}; calculadora.divir = function (x, y) { return x / y }
- /multiplicar.js
var calculadora = calculadora || {}; calculadora.multiplicar = function (x, y) { return x * y }
Usando Require.js
-
AMD:
-
index.html:
<script data-main="calculadora" src="require.js"></script>
- /calculadora.js
require(['calculadora/sumar', 'calculadora/restar', 'calculadora/cuadrado'], function (sum, res, cua) { console.info(sum(1,2)); // 1 + 2 console.info(res(3,1)); // 3 - 1 console.log(cua(2)); // 2 * 2 });
- calculadora/sumar.js
define(function () { return function (x, y) { return x + y; }; });
- calculadora/restar.js
define(function () { return function (x, y) { return x - y; }; });
- calculadora/multiplicar.js
define(function () { return function (x, y) { return x * y; }; });
- calculadora/cuadrado.js
define(['calculadora/multiplicar'], function (multiplicar) { return function (x) { return multiplicar(x, x); }; });
Require.js - Modo Avanzado
-
Require.js con dependencias externas:
-
vendor/jquery.min.js (en local)
-
script.js
require(['vendor/jquery'], function($){ $('#hola').html("<h1>HOLA! Hola!</h1>"); });
-
-
Require.js varios modulos en el mismo archivo:
- script.js
require(['hola', 'adios'], function(hola, adios){ $('#hola').html("<h1>"+hola+" y "+adios+"!</h1>"); });
- hola.js
define(function() { return "Hola"; }); define('adios', function() { return "adios"; });
-
Require.js configurando baseUrl:
- Estructura del proyecto:
www/ /assets/ /css/ /js/ /App/ main.js /vendor/ bootstrap.js jquery.js
- config.js:
requirejs.config({ baseUrl: '.assets/js' });
- *.js
require(['vendor/jquery', 'vendor/bootstrap', 'app/main']);
-
Require.js configurando Paths:
- Estructura del proyecto:
www/ /assets/ /css/ /js/ /app/ main.js /vendor/ bootstrap.js jquery.js
- config.js:
requirejs.config({ baseUrl: '.assets/js', paths: { 'jquery': 'vendor/jquery', 'bootstrap': 'vendor/bootstrap', 'main': 'app/main' } });
- *.js:
require(['jquery', 'bootstrap', 'main']);
- Colección de patrones de Javascript de Shi Chuan
- Libro "Essential Javascript Design Patterns" de Addy Osmani
- Libro "JavaScript Patterns" de Stoyan Stefanov
- Introducción al diseño de algoritmos en Javascript
- Algorithm Visualizer
- Minimal and clean examples of machine learning algorithms
- Torch implementation of neural style algorithm
- Collection of classic computer science paradigms, algorithms, and approaches written in JavaScript.
- JavaScript implementation of different computer science algorithms
- Atwood's Law applied to CS101 - Classic algorithms and data structures implemented in JavaScript