PROMESAS… PROMESAS…

<script src=”other pages” title=”promesas promesas”>

No, este post no va de dubstep ni del video de arriba (¿pero si que mola, no? 😉 )

¿Qué es eso de las “Promesas”?

Una promesa es un encapsulamiento de una operación invocada de forma asíncrona. Para ilustrar esto, digamos que se requiere hacer la siguiente operación:

var arreglo = [...]; //10000 elementos
for (var i = 0; i < arreglo.length; i++) {
	//hacer otras cosas con el arreglo
	if (i == 4000){
		return i;
	}
};
	//...
	//hacer más cosas
var otraFuncion = function(i){
	//hacer otras cosas con i
};

otraFuncion(i);

Tal vez este ejemplo sea un poco rebuscado pero es para aclarar el comportamiento de Javascript cuando la mayor parte del tiempo se programa de forma síncrona. Básicamente, lo que sucede en este caso, es que la función otraFuncion no va a ejecutarse hasta que no se haya terminado el ciclo for. En este caso, se requiere recorrer el arreglo por lo menos unas 4000 veces, lo cual en términos de CPU, representa un consumo importante y un retraso en la ejecución del programa.

Afortunadamente, Javascript cuenta con los callbacks, cuya funcionalidad principal consiste en ser pasados como argumentos a funciones del flujo principal del programa. Mientras que en el primer caso, otraFuncion espera a que el ciclo for sea ejecutado para llamarse, en el mecanismo de callbacks, la espera no es necesaria para el flujo principal del programa:

var arreglo = [...]; //10000 elementos
var cicloFor = function(arreglo){
	for (var i = 0; i < arreglo.length; i++) {
		//hacer otras cosas con el arreglo
		if (i == 4000){
			return i;
		}
	};
};
var otraFuncion = function(i){
	//hacer otras cosas con el indice y ejecutarla
};
var miPrograma = function(cicloFor, otraFuncion){
	var indice = cicloFor();
	if(indice != 4000) {
		otraFuncion();
	} else {
		//hacer algo más...
	}
};

miPrograma(cicloFor, otraFuncion);

El programa se ejecutará ligeramente más rápido que el primer caso, ya que no hay que esperar a que el ciclo for termine. Adicionalmente se encapsula la lógica de la aplicación en una sola funcion y no en dos. Sin embargo, este “acercamiento” presenta al menos tres inconvenientes:

  • Funciones como parámetros, es algo que generalmente causa confusión a los programadores novatos (como yo 😛 ) en Javascript.
  • La lógica de programación no siempre puede ser encapsulada de este modo (a veces es obligatorio trabajar de forma síncrona.
  • Es muy probable que algunos errores generados por los callbacks no sean capturados.

Personalmente, cuando escribí este ejemplo, se me hizo bastante complicado presentar un ejemplo claro en el que pudieran trabajar, sin mencionar que es seguro que este código arroje errores impredecibles, bien sea no capturar los errores en el flujo “secundario” que generan los callbacks o por la lógica de la aplicación en sí. Para esto son las promesas.

¿Qué facilita las “Promesas”?

Las “promesas” pueden ser encadenadas a cualquier objeto en Javascript, permiten manejo asíncrono de errores y una sintaxis más limpia en cuanto a llamadas asíncronas de funciones se refiere. Digamos que una función retorna una Promesa (en inglés, Promise) cuando el objeto requiere de un flujo alternativo, por ejemplo, en el caso de un flujo condicional típico:

if(condicion_1){
	//ejecutar una funcion o algo
} else if(condicion_2){
	//hacer otra cosa
} else if(condicion_3){
	//ejecutar otra funcion
} else if (...){
	//...
} else if (condicion_N){
	//hacer algo más
}

Este flujo condicional puede ser reescrito como Promesas:

return new Promise(
    function(){
        //callback que encapsula la Promesa
    }
).then(
    function(valores){
        //comportamiento si callback es exitoso
    },
    function(err){
        //comportamiento si callback es erróneo
    }
).then(
    //otros comportamientos alternativos...
);

¿Y cómo se comporta una “Promesa”?

Un objeto de tipo Promise tiene tres estados básicos:

  • Se dice que está pending (pendiente) si el objeto no ha utilizado ninguno de los callbacks anclados a si mismo. Este es el estado inicial de todo objeto Promise.
  • Se dice que está fullfilled cuando el objeto utilizó el callback que encapsula, e informa que dicho callback fue realizado de manera exitosa.
  • Se dice que está rejected cuando el objeto no utilizó el callback que encapsula, e informa que dicho callback generó un error.

Una vez que el objeto informó que el callback fue utilizado (sea la llamada exitosa o errónea), no se puede cambiar su estado, es decir, debe generarse un nuevo objeto Promise si se necesita. Un ejemplo más claro de la utilidad de una Promesa, es cuando se poseen llamadas AJAX a rutas de recursos:

get('data.json').then(function(response) {
	console.log("Success!", response); //Éxito!
}, function(error) {
	console.log("Failed!", error); //Error!
});

Puedes ver más información sobre la API Promises de Javascript aquí, o ver un tuto bien chévere aquí.

Por lo pronto, y de mi parte, prometo usar las promesas (valga la “rebuznancia” 😛 ) en alguna parte de los tutos de mi blog… Más adelante 😉

</script>

Anuncios

2 comentarios en “PROMESAS… PROMESAS…

Los comentarios están cerrados.