2010-05-26 13 views
14

Ho bisogno di eseguire una serie di metodi asincroni (database SQLite client) e chiamare solo un callback finale.javascript: esegue un gruppo di metodi asincroni con una callback

Naturalmente, il modo brutto è:

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

ma so che ci sono modi migliori per farlo. Intuitivamente rileverei quando tutte le richiamate sono state chiamate con un contatore per chiamare la callback finale.

Credo che questo sia un comune design-pattern, quindi se qualcuno mi potrebbe punto nella giusta direzione ...

Grazie in anticipo!

risposta

20

questo è facile

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

semplicemente passare questo callback per tutti i metodi, e una volta che è stato chiamato 4 volte esso verrà eseguito.

Se si desidera utilizzare fabbrica per questo allora si può fare la seguente

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

E se esiste un tale schema, allora è questo. –

+0

Grazie mille Sean, è stato facile e implementare qualcosa come la tua prima soluzione prima di vedere la tua risposta. Ma mi piace di più la tua fabbrica di callback, è molto elegante, la userò ;-) – Samuel

+0

E se è un modello, deve avere un nome. Suggerimenti ?! – ThomasH

8

Ho scritto alcune utilità asincroni potreste trovare utile, che consente di scrivere il vostro esempio come:

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

O, se si voleva correre in parallelo, come:

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

ci sono un sacco di altro uso funzioni ful come mappa async/ridurre troppo:

http://caolanmcmahon.com/async.html

Speranza che aiuta!

0

Le promesse possono aiutare a gestire questo. Esistono due scenari generali: parallelo e seriale. Il parallelismo può essere realizzato usando Promise.all(), il serial è più complesso - l'attività B può essere avviata solo quando l'attività A è terminata. Ecco un esempio ridotto all'osso:

// 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")); 

Potrebbero aver bisogno di traduzione ES6/7 per fare questo lavoro nei browser o versioni più vecchie dei nodi.

Problemi correlati