Você não foi muito específico com seu código, então vou inventar um cenário. Digamos que você tenha 10 chamadas ajax e deseja acumular os resultados dessas 10 chamadas ajax e, quando todas elas forem concluídas, você deseja fazer algo. Você pode fazer isso assim, acumulando os dados em uma matriz e acompanhando quando o último foi concluído:
Contador Manual
var ajaxCallsRemaining = 10;
var returnedData = [];
for (var i = 0; i < 10; i++) {
doAjax(whatever, function(response) {
// success handler from the ajax call
// save response
returnedData.push(response);
// see if we're done with the last ajax call
--ajaxCallsRemaining;
if (ajaxCallsRemaining <= 0) {
// all data is here now
// look through the returnedData and do whatever processing
// you want on it right here
}
});
}
Nota: o tratamento de erros é importante aqui (não mostrado porque é específico para como você está fazendo suas chamadas ajax). Você vai querer pensar sobre como vai lidar com o caso em que uma chamada de ajax nunca é concluída, seja com um erro ou travada por um longo tempo ou expira após um longo tempo.
jQuery Promises
Somando-se a minha resposta em 2014. Hoje em dia, as promessas costumam ser usadas para resolver esse tipo de problema, já que a jQuery's $.ajax()
já retorna uma promessa e $.when()
avisará quando um grupo de promessas for resolvido e coletará os resultados de retorno para você:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push($.ajax(...));
}
$.when.apply($, promises).then(function() {
// returned data is in arguments[0][0], arguments[1][0], ... arguments[9][0]
// you can process it here
}, function() {
// error occurred
});
ES6 Standard Promises
Conforme especificado na resposta de kba : se você tem um ambiente com promessas nativas integradas (navegador moderno ou node.js ou usando transpile babeljs ou usando um polyfill de promessa), então você pode usar promessas especificadas no ES6. Consulte esta tabela para suporte ao navegador. As promessas são suportadas em praticamente todos os navegadores atuais, exceto o IE.
Se doAjax()
retornar uma promessa, você pode fazer o seguinte:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
Se você precisar transformar uma operação assíncrona sem promessa em uma que retorne uma promessa, poderá "prometê-la" assim:
function doAjax(...) {
return new Promise(function(resolve, reject) {
someAsyncOperation(..., function(err, result) {
if (err) return reject(err);
resolve(result);
});
});
}
E, em seguida, use o padrão acima:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
Bluebird Promises
Se você usar uma biblioteca com mais recursos, como a biblioteca de promessa do Bluebird , ela terá algumas funções adicionais integradas para tornar isso mais fácil:
var doAjax = Promise.promisify(someAsync);
var someData = [...]
Promise.map(someData, doAjax).then(function(results) {
// all ajax results here
}, function(err) {
// some error here
});