2010-05-26 6 views
14

Necesito ejecutar un grupo de métodos asíncronos (base de datos SQLite del cliente) y llamar solo a una devolución de llamada final.javascript: ejecuta un montón de método asíncrono con una devolución de llamada

Por supuesto, el camino es fea:

execAll : function(callBack) { 
     asynch1(function() { 
      asynch2(function() { 
       ... 
       asynchN(function() { 
        callBack(); 
       }) 
      }) 
     }); 
    } 

Pero sé que hay mejores maneras de hacerlo. Intuitivamente detectaría cuando se ha llamado a toda devolución de llamada con un contador para llamar a la devolución de llamada final.

Creo que este es un diseño-patrón común, así que si alguien me podría apuntar en la dirección correcta ...

Gracias de antemano!

Respuesta

20

esto es fácil

var callback = (function(){ 
    var finishedCalls = 0; 
    return function(){ 
     if (++finishedCalls == 4){ 
      //execute your action here 
     } 
    }; 
})(); 

sólo tiene que pasar esta devolución de llamada a todos sus métodos, y una vez que se ha llamado 4 veces que se ejecutará.

Si desea utilizar la fábrica para esto, entonces usted puede hacer lo siguiente

function createCallback(limit, fn){ 
    var finishedCalls = 0; 
    return function(){ 
     if (++finishedCalls == limit){ 
      fn(); 
     } 
    }; 
} 


var callback = createCallback(4, function(){ 
    alert("woot!"); 
}); 


async1(callback); 
async2(callback); 
async3(callback); 
async4(callback); 
+1

Y si existe tal patrón, entonces esto es todo. –

+0

Muchas gracias Sean, fue fácil, e implementar algo así como tu primera solución antes de ver tu respuesta. Pero me gusta más su fábrica de devolución de llamada, es muy elegante, la usaré ;-) – Samuel

+0

Y si es un patrón, tiene que tener un nombre. Sugerencias? – ThomasH

8

He escrito algunas empresas de servicios asincrónicos le puede resultar útil, que le permite escribir tu ejemplo como:

function(callback) { 
    async.series([ 
     asynch1(), 
     asynch2(), 
     ... 
     asynchN() 
    ], callback); 
} 

O bien, si desea ejecutar en paralelo, como:

function(callback) { 
    async.parallel([ 
     asynch1(), 
     asynch2(), 
     ... 
     asynchN() 
    ], callback); 
} 

hay un montón de otros usos ful funciones como mapa asíncrono/reducir demasiado:

http://caolanmcmahon.com/async.html

espero que ayude!

0

Las promesas pueden ayudar a gestionar esto. Hay dos escenarios generales: paralelo y serial. Paralelo se puede lograr utilizando Promise.all(), serial es más complejo, la tarea B solo puede comenzar cuando se realiza la tarea A. He aquí una muestra escueto:

// returns a promise that resolves as the task is done 
const wrap = (fn, delay) => new Promise(resolve => setTimeout(_ => resolve(fn()), delay)); 
const task = (fn, delay) => delay ? wrap(fn, delay) : Promise.resolve(fn()); 

// given a list of promises, execute them one by one. 
const sequence = async l => l.reduce(async (a, b) => [].concat(await a, await b)); 

const tasks = [ 
    task(_ => console.log("hello world")), 
    task(_ => console.log("hello future"), 1000) 
]; 

sequence(tasks).then(_ => console.log("all done")); 

Es posible que tenga alguna traducción ES6/7 para que esto funcione en los navegadores o versiones más viejas del nodo.

Cuestiones relacionadas