Vamos a comparar el ejemplo promesa de un ejemplo de JavaScript puro:
// First we need a convenience function for W3C's fiddly XMLHttpRequest.
// It works a little differently from the promise framework. Instead of
// returning a promise to which we can attach a handler later with .then(),
// the function accepts the handler function as an argument named 'callback'.
function requestSomeDataAndCall(url, callback) {
var req = new XMLHttpRequest();
req.onreadystatechange = resHandler;
req.open("GET", url, false);
req.send();
function resHandler() {
if (this.readyState==4 && this.status==200) {
callback(this);
} else {
// todo: Handle error.
}
}
}
requestSomeDataAndCall("http://example.com/foo", function(res){
setTimeout(function(){
var data = JSON.parse(res.responseText);
setTimeout(function(){
var price = data.price;
setTimeout(function(){
print("The price is "+price);
},10);
},10);
},10);
});
Como Norbert señaló Hartl, JSON.parse() colgará el navegador para grandes cadenas. Así que utilicé setTimeout() para retrasar su ejecución (después de una pausa de 10 milisegundos). Este es un ejemplo de la solución de Kris Kowal. Permite completar el hilo de Javascript actual, liberando el navegador para presentar los cambios DOM y desplazarse por la página para el usuario, antes de ejecutar la devolución de llamada.
Espero que el framework de promesa commonjs también use algo como setTimeout, de lo contrario, las últimas promesas en el ejemplo del artículo se ejecutarán sincrónicamente como se temía.
Mi alternativa anterior parece bastante fea, con los procesos posteriores que requieren más sangría. Reestructuré el código, por lo que podemos ofrecer nuestra cadena de procesos todo en una planta:
function makeResolver(chain) {
function climbChain(input) {
var fn = chain.shift(); // This particular implementation
setTimeout(function(){ // alters the chain array.
var output = fn(input);
if (chain.length>0) {
climbChain(output);
}
},10);
}
return climbChain;
}
var processChain = [
function(response){
return JSON.parse(response.body);
},
function(data){
return data.price; // get the price
},
function(price){
print("The price is " + price);
}
];
var climber = makeResolver(promiseChain);
requestSomeDataAndCall("http://example.com/foo", climber);
Tenía la esperanza de demostrar que tradicional visión de paso de las devoluciones de llamada en Javascript es más o menos equivalente a las promesas. Sin embargo, después de dos intentos, parezco haber demostrado, con referencia a la pulcritud del código en el ejemplo original, ¡que las promesas son una solución mucho más elegante!
Usted tienen razón, no tiene sentido usar promesas para operaciones sincrónicas. Entonces el resultado debe ser igual. Pero luego es un ejemplo e ilustra el uso de la promesa. Para el código que se ejecuta después de su ejemplo, de hecho hay una diferencia. Si necesita ejecutar algo después del ejemplo de lo que puede hacerlo (utilizando el enfoque de promesa) sin saber nada sobre lo que hace el código de ejemplo –