Javascript 如何等待一组异步回调函数?

Javascript 如何等待一组异步回调函数?,javascript,asynchronous,Javascript,Asynchronous,我的代码在javascript中看起来像这样: forloop { //async call, returns an array to its callback } 在所有这些异步调用完成之后,我想计算所有数组的最小值 我怎么能等他们呢 我现在唯一的想法是让一个布尔数组名为done,并在第i个回调函数中将done[i]设置为true,然后说while(不是所有的都完成了){} edit:我认为一个可能但难看的解决方案是在每个回调中编辑done数组,然后在每个回调中设置了所有其他done

我的代码在javascript中看起来像这样:

forloop {
    //async call, returns an array to its callback
}
在所有这些异步调用完成之后,我想计算所有数组的最小值

我怎么能等他们呢

我现在唯一的想法是让一个布尔数组名为done,并在第i个回调函数中将done[i]设置为true,然后说while(不是所有的都完成了){}

edit:我认为一个可能但难看的解决方案是在每个回调中编辑done数组,然后在每个回调中设置了所有其他done的情况下调用一个方法,因此最后一个要完成的回调将调用continue方法

提前感谢。

您可以将jQuery的对象与方法一起使用

可以将jQuery的对象与方法一起使用


您的代码不是很具体,所以我将编写一个场景。假设您有10个ajax调用,您希望累积这10个ajax调用的结果,然后当它们全部完成时,您希望做一些事情。您可以通过在数组中累积数据并跟踪最后一个数据完成的时间来执行此操作:

手动计数器

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
        }
    });
}

ES6标准承诺

:如果您的环境内置了本机承诺(modern browser或node.js或使用babeljs Transfile或使用promise polyfill),则可以使用ES6指定的承诺。有关浏览器支持的信息,请参见。除了IE之外,几乎所有当前浏览器都支持承诺

如果
doAjax()
返回承诺,则可以执行以下操作:

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
});
然后使用上面的模式:

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
});

您的代码不是很具体,所以我将编写一个场景。假设您有10个ajax调用,您希望累积这10个ajax调用的结果,然后当它们全部完成时,您希望做一些事情。您可以通过在数组中累积数据并跟踪最后一个数据完成的时间来执行此操作:

手动计数器

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
        }
    });
}

ES6标准承诺

:如果您的环境内置了本机承诺(modern browser或node.js或使用babeljs Transfile或使用promise polyfill),则可以使用ES6指定的承诺。有关浏览器支持的信息,请参见。除了IE之外,几乎所有当前浏览器都支持承诺

如果
doAjax()
返回承诺,则可以执行以下操作:

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
});
然后使用上面的模式:

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
});

您可以这样模拟它:

function doAjax(...) {
    return new Promise(function(resolve, reject) {
        someAsyncOperation(..., function(err, result) {
            if (err) return reject(err);
            resolve(result);
        });
    });
}
  countDownLatch = {
     count: 0,
     check: function() {
         this.count--;
         if (this.count == 0) this.calculate();
     },
     calculate: function() {...}
  };
然后,每个异步调用都会执行以下操作:

countDownLatch.count++;
在方法末尾的每个异步回调中,添加以下行:

countDownLatch.check();

换句话说,您可以模拟倒计时闩锁功能。

您可以这样模拟它:

function doAjax(...) {
    return new Promise(function(resolve, reject) {
        someAsyncOperation(..., function(err, result) {
            if (err) return reject(err);
            resolve(result);
        });
    });
}
  countDownLatch = {
     count: 0,
     check: function() {
         this.count--;
         if (this.count == 0) this.calculate();
     },
     calculate: function() {...}
  };
然后,每个异步调用都会执行以下操作:

countDownLatch.count++;
在方法末尾的每个异步回调中,添加以下行:

countDownLatch.check();

换句话说,您可以模拟倒计时锁存功能。

使用控制流库,如


使用控制流库,如


从2015年开始入住:我们现在已经入住(Edge 12、Firefox 40、Chrome 43、Safari 8、Opera 32、Android浏览器4.4.4和iOS Safari 8.4,但不包括Internet Explorer、Opera Mini和旧版本的Android)

如果我们希望执行10个异步操作并在它们全部完成时收到通知,我们可以使用本机,而不需要任何外部库:

function asyncAction(i) {
    return new Promise(function(resolve, reject) {
        var result = calculateResult();
        if (result.hasError()) {
            return reject(result.error);
        }
        return resolve(result);
    });
}

var promises = [];
for (var i=0; i < 10; i++) {
    promises.push(asyncAction(i));
}

Promise.all(promises).then(function AcceptHandler(results) {
    handleResults(results),
}, function ErrorHandler(error) {
    handleError(error);
});
函数异步动作(i){
返回新承诺(功能(解决、拒绝){
var result=calculateResult();
if(result.hasError()){
返回拒绝(result.error);
}
返回解析(结果);
});
}
var承诺=[];
对于(变量i=0;i<10;i++){
承诺.推送(异步动作(i));
}
Promise.all(promises).then(函数AcceptHandler(结果){
HandlerResults(结果),
},函数ErrorHandler(错误){
handleError(错误);
});

从2015年开始入住:我们现在有了(Edge 12、Firefox 40、Chrome 43、Safari 8、Opera 32、Android浏览器4.4.4和iOS Safari 8.4,但没有Internet Explorer、Opera Mini和Android的旧版本)

如果我们希望执行10个异步操作并在它们全部完成时收到通知,我们可以使用本机,而不需要任何外部库:

function asyncAction(i) {
    return new Promise(function(resolve, reject) {
        var result = calculateResult();
        if (result.hasError()) {
            return reject(result.error);
        }
        return resolve(result);
    });
}

var promises = [];
for (var i=0; i < 10; i++) {
    promises.push(asyncAction(i));
}

Promise.all(promises).then(function AcceptHandler(results) {
    handleResults(results),
}, function ErrorHandler(error) {
    handleError(error);
});
函数异步动作(i){
返回新承诺(功能(解决、拒绝){
var result=calculateResult();
if(result.hasError()){
返回拒绝(result.error);
}
返回解析(结果);
});
}
var承诺=[];
对于(变量i=0;i<10;i++){
承诺.推送(异步动作(i));
}
Promise.all(promises).then(函数AcceptHandler(结果){
HandlerResults(结果),
},函数ErrorHandler(错误){
handleError(错误);
});

我认为这是最简洁的方式

(由于某些原因,Array.map在.then函数中不起作用。但您可以使用.forEach和[].concat()或类似的函数)


在我看来,这是最简洁的方式

(由于某些原因,Array.map在.then函数中不起作用。但您可以使用.forEach和[].concat()或类似的函数)


在async上,您是说等待Ajax请求完成吗?注意,
while(并非全部完成){}
不起作用。当您忙于等待时,您的任何回调都无法运行。是的。我正在等待对外部API的异步调用返回,以便它触发回调方法。是的,我意识到了这一点,这就是我在这里寻求帮助的原因:DYou可以尝试以下方法:非常好的一组异步实用程序函数。在异步上,你的意思是等待Ajax请求完成吗?注意,
while(并非全部完成){}
不起作用。当您忙于等待时,您的任何回调都无法运行。是的。我正在等待对外部API的异步调用返回,以便它触发回调方法。是的,我意识到了这一点,这就是我在这里寻求帮助的原因:DYou可以试试这个:非常好的异步实用程序函数集