when then promises examples done javascript jquery jquery-deferred waterfall

javascript - then - Bucle asíncrono de jQuery Aplazados(promesas)



jquery submit promise (5)

Desafío interesante por cierto. Lo que he encontrado es una función recursiva que acepta una lista y un índice de inicio opcional.

Aquí hay un enlace al jsFiddle que he probado con diferentes intervalos e intervalos de lista.

Supongo que tiene una lista de funciones que devuelven promesas (no una lista de números). Si tiene una lista de números, cambiaría esta parte.

$.when(tasks[index]()).then(function(){ deferredSequentialDo(tasks, index + 1); });

a esto

/* Proxy is a method that accepts the value from the list and returns a function that utilizes said value and returns a promise */ var deferredFunction = myFunctionProxy(tasks[index]); $.when(tasks[index]()).then(function(){ deferredSequentialDo(tasks, index + 1); });

No estoy seguro de qué tan grande podría ser su lista de funciones, pero tenga en cuenta que el navegador conservará los recursos de la primera llamada de Aplazado de Diferencias de Diferencias hasta que estén terminadas.

Estoy tratando de crear lo que creo que se conoce como una "cascada". Quiero procesar secuencialmente una serie de funciones asíncronas (jQuery promete).

Aquí hay un ejemplo artificial:

function doTask(taskNum){ var dfd = $.Deferred(), time = Math.floor(Math.random()*3000); setTimeout(function(){ console.log(taskNum); dfd.resolve(); },time) return dfd.promise(); } var tasks = [1,2,3]; for (var i = 0; i < tasks.length; i++){ doTask(tasks[i]); } console.log("all done");

Me gustaría que completara la tarea en el orden en que se ejecutan (presente en la matriz). Entonces, en este ejemplo, quiero que haga la tarea 1 y espere a que se resuelva, luego haga la tarea 2, espere a que se resuelva, haga la tarea 3, etc. y el registro "todo listo".

Tal vez esto sea realmente obvio, pero he estado tratando de resolver esto toda la tarde.


Eche un vistazo a los métodos de $.when y then para ejecutar diferidos.

Las cascadas se utilizan para canalizar los valores de retorno de uno a otro, en serie. Se vería algo como esto .

function doTask (taskNum) { var dfd = $.Deferred(), time = Math.floor(Math.random() * 3000); console.log("running task " + taskNum); setTimeout(function(){ console.log(taskNum + " completed"); dfd.resolve(taskNum + 1); }, time) return dfd.promise(); } var tasks = [1, 2, 3]; tasks .slice(1) .reduce(function(chain) { return chain.then(doTask); }, doTask(tasks[0])) .then(function() { console.log("all done"); });

Tenga en cuenta el argumento pasado para resolve . Eso pasa a la siguiente función en la cadena. Si solo desea ejecutarlos en serie sin canalizar los argumentos, puede eliminar eso y cambiar la reducción de llamada a .reduce(function(chain, taskNum) { return chain.then(doTask.bind(null, taskNum)); }, doTask(tasks[0]));

Y en paralelo se vería así :

var tasks = [1,2,3].map(function(task) { return doTask(task); }); $.when.apply(null, tasks).then(function() { console.log(arguments); // Will equal the values passed to resolve, in order of execution. });


Intentaría usar la $().queue lugar de $.Deferred aquí. Agregue las funciones a una cola y solo llame a la siguiente cuando esté listo.

function doTask(taskNum, next){ var time = Math.floor(Math.random()*3000); setTimeout(function(){ console.log(taskNum); next(); },time) } function createTask(taskNum){ return function(next){ doTask(taskNum, next); } } var tasks = [1,2,3]; for (var i = 0; i < tasks.length; i++){ $(document).queue(''tasks'', createTask(tasks[i])); } $(document).queue(''tasks'', function(){ console.log("all done"); }); $(document).dequeue(''tasks'');


Para una cascada, necesitas un bucle asíncrono:

(function step(i, callback) { if (i < tasks.length) doTask(tasks[i]).then(function(res) { // since sequential, you''d usually use "res" here somehow step(i+1, callback); }); else callback(); })(0, function(){ console.log("all done"); });


Puede crear un $ .Deferred resuelto y simplemente agregarlo a la cadena con cada iteración:

var dfd = $.Deferred().resolve(); tasks.forEach(function(task){ dfd = dfd.then(function(){ return doTask(task); }); });

Paso a paso ocurre lo siguiente:

//begin the chain by resolving a new $.Deferred var dfd = $.Deferred().resolve(); // use a forEach to create a closure freezing task tasks.forEach(function(task){ // add to the $.Deferred chain with $.then() and re-assign dfd = dfd.then(function(){ // perform async operation and return its promise return doTask(task); }); });

Personalmente, me parece más limpio que la recursión y más familiar que $ (). Queue (jQuery API for $ (). La cola es confusa ya que está diseñada para animaciones, también es probable que esté usando $ .Deferred''s en otros lugares en su código). También tiene los beneficios de la transferencia estándar de resultados a través de la resolución () en la operación asíncrona y permite la conexión de una propiedad de $ .done.

Aquí está en un jsFiddle