javascript - then - jQuery Deferred and Promise para la ejecución secuencial de funciones síncronas y asíncronas
promise javascript ejemplo (3)
Si quiero que las funciones sincrónicas y asíncronas se ejecuten en un orden particular, podría usar la promesa de jQuery, pero no parece funcionar de la manera que esperaría que funcionara.
Las funciones a, byc deben ejecutarse en ese orden cuando en a deferred.resolve()
Se llama a resuelve deferred.resolve()
. Esperaría que se ejecutara la función b pero todas las funciones se ejecutan inmediatamente sin importar si se llama a la resolución.
Aquí está el código:
function a(){
var deferred = $.Deferred();
setTimeout(function(){
console.log("status in a:",deferred.state());
//this should trigger calling a or not?
deferred.resolve("from a");
},200);
console.log("a");
return deferred.promise();
};
function b(){
var deferred = $.Deferred();
setTimeout(function(){
console.log("status in b:",deferred.state());
deferred.resolve("from b");
},200);
console.log("b");
return deferred.promise();
}
//synchronous function
function c(){
var deferred = $.Deferred();
console.log("c");
console.log("status in c:",deferred.state());
deferred.resolve("from c");
return deferred.promise();
}
function test(){
fn=[a,b,c],i=-1,
len = fn.length,d,
d = jQuery.Deferred(),
p=d.promise();
while(++i<len){
p=p.then(fn[i]);
}
p.then(function(){
console.log("done");
},
function(){
console.log("Failed");
});
d.resolve();
//instead of the loop doing the following has the same output
//p.then(a).then(b).then(c);
//d.resolve();
}
test();
La salida es:
a
b
status in c: pending
c
done
status in a: pending
status in b: pending
Rendimiento esperado:
a
status in a: pending
b
status in b: pending
c
status in c: pending
done
Intenté algunas combinaciones de las siguientes modificaciones:
d = jQuery.Deferred();
setTimeout(function(){d.resolve();},100);
var p=d.promise();
while(++i<len){
p.then(fn[i]);
}
Pero todos con los mismos resultados inesperados, b se llama antes de que se resuelva el diferido de a, c se convoca antes de que se resuelva el diferido de b.
Para jQuery anterior a la 1.8, esto es un problema, pero para las nuevas versiones de jQuery, esto ya no es un problema:
function test(){
var d = jQuery.Deferred(),
p=d.promise();
//You can chain jQuery promises using .then
p.then(a).then(b).then(c);
d.resolve();
}
test();
Debajo está la demo de jQuery 1.7.2
jQuery <1.8 está bien encadenamiento WRT, solo usa .pipe
lugar de .then
. 1.8 simplemente cambió .then
ser .pipe
.
Nota: Cuando lo usas sin la matriz, no tienes que comenzar con una promesa. $.when({}).then(a).then(b)
hará bien el truco. Solo necesita asegurarse de no colocar a
when
.