Un'alternativa più pulita a quanto suggerito da @Ivo sarebbe una coda del metodo asincrono , supponendo che sia necessario effettuare solo una chiamata asincrona per la raccolta.
(Vedi questo post di Dustin Diaz per una spiegazione più dettagliata)
function Queue() {
this._methods = [];
this._response = null;
this._flushed = false;
}
(function(Q){
Q.add = function (fn) {
if (this._flushed) fn(this._response);
else this._methods.push(fn);
}
Q.flush = function (response) {
if (this._flushed) return;
this._response = response;
while (this._methods[0]) {
this._methods.shift()(response);
}
this._flushed = true;
}
})(Queue.prototype);
È sufficiente creare una nuova istanza di Queue, aggiungere i callback necessari e quindi svuotare la coda con la risposta asincrona.
var queue = new Queue();
queue.add(function(results){
for (var result in results) {
}
});
someFunction(param1, param2, function(results) {
queue.flush(results);
}
Un ulteriore vantaggio di questo modello è che puoi aggiungere più funzioni alla coda invece di una sola.
Se hai un oggetto che contiene funzioni iteratore, puoi aggiungere il supporto per questa coda dietro le quinte e scrivere codice che sembra sincrono, ma non lo è:
MyClass.each(function(result){ ... })
scrivi semplicemente eachper mettere la funzione anonima nella coda invece di eseguirla immediatamente, quindi svuota la coda quando la tua chiamata asincrona è completa. Questo è un modello di progettazione molto semplice e potente.
PS Se stai usando jQuery, hai già una coda del metodo asincrono a tua disposizione chiamata jQuery.Deferred .
( /* ... */ )sembra un mostro e ora ho paura :(