这是我目前使用的代码,
function loopArrayWithAsync(array, doSthWithElement, finalCallback) {
var count = 0;
var _data = [];
var _errs = [];
for (var i = 0; i < array.length; i++) {
doSthWithElement(array[i], function (err, data) {
count++;
if (err) {
_errs.push(err);
}
if (data) {
_data.push(data);
}
if (count === data.length) {
finalCallback(_errs, _data);
}
}
}
}
然后,我将以这种方式使用该功能:
loopArrayWithAsync(array, function (element, finish) {
// element - element in the array
asyncFunc(element, function (err, result) {
if (err) {
finish(err);
} else {
finish(null, result);
}
});
}, function (errs, finalData) {
// when the for loop is finished,
// i.e. (count === data.length)
// this callback will be executed
// errs - array of err from the above callback function
// finalData - array of result from the above callback function
outerCallback(errs, finalData);
});
通过这个实现,我可以循环使用异步函数的数组,并在处理完数组中的所有元素时执行回调函数。
但现在我想为loopArrayWithAsync()
添加延迟/间隔功能 像loopArrayWithAsync(array, {interval : 1000}, function (element, finish) {...
之类的东西,在处理完第一个元素之后,应该等待1000毫秒,然后开始处理第二个元素,反之亦然...
我发现另一个question正在谈论为for loop添加延迟
但在处理异步函数时似乎更复杂。
任何答案都将不胜感激
============================== update ================ ==============
这是重构后的功能,
function loopArrayWithAsync(array, options, doSthWithElement, finalCallback) {
if (isFunction(options)) {
finalCallback = doSthWithElement;
doSthWithElement = options;
options = {};
}
options.interval = options.interval || 0;
options.oneByOne = options.oneByOne || false;
var _data = [];
var _errs = [];
var count = 0;
var length = array.length;
var i = 0;
(function handleIteration() {
if (i < length) {
var element = array[i];
doSthWithElement(element, function (err, data) {
if (err) {
_errs.push(err);
}
if (data) {
_data.push(data);
}
count++;
if (count === length) {
finalCallback(_errs, _data);
} else if (options.oneByOne) {
if (options.interval) {
setTimeout(handleIteration, options.interval);
} else {
process.nextTick(handleIteration);
}
}
});
i++;
if (!options.oneByOne) {
if (options.interval) {
setTimeout(handleIteration, options.interval);
} else {
process.nextTick(handleIteration);
}
}
}
}());
};
这样我现在就可以这样使用这个功能了:
loopArrayWithAsync(array, {interval : 1000}, function (element, finish) {
asyncFunc(element, function (err, result) {
if (err) {
finish(err);
} else {
anotherAsyncFunc(result, function (err, doc) {
if (err) {
finish(err);
} else {
finish(null, doc);
}
});
}
});
}, function (errs, finalData) {
outerCallback(errs, finalData);
});
或
loopArrayWithAsync(array, {oneByOne : true}, function (element, finish) {...
逐个循环遍历元素
loopArrayWithAsync(array, {interval : 5000, oneByOne : true}, function (element, finish) {...
逐个循环遍历元素并延迟5秒
可用选项:
interval
是每次迭代之间的毫秒数,默认值为:0
如果oneByOne
为真,则该方法只会在为当前元素调用finish
之前进入下一个元素,默认值为:false
代码现在适合我的情况,但我仍然会尝试使用建议的库来让生活更轻松,谢谢
如果您发现代码可以进一步改进,请发表评论,期待任何建议!
答案 0 :(得分:0)
您可以使用本地函数进行异步循环。对于下一次迭代,函数调用自身的延迟:
function loopArrayWithAsync(array, doSthWithElement, finalCallback, delay) {
var _data = [], _errs = [], i = 0;
loop();
function loop() {
doSthWithElement(array[i], function (err, data) {
if (err) {
_errs.push(err);
}
if (data) {
_data.push(data);
}
i++;
if (i === array.length) {
finalCallback(_errs, _data);
} else {
window.setTimeout(loop, delay);
}
}
}
}
要以特定间隔开始通话而不是在通话之间有延迟,只需在不同时间使用setInterval
:
function loopArrayWithAsync(array, doSthWithElement, finalCallback, delay) {
var _data = [], _errs = [], count = 0;
for (var i = 0; i < array.length; i++) {
window.setTimeout(function() {
doSthWithElement(array[i], function (err, data) {
if (err) {
_errs.push(err);
}
if (data) {
_data.push(data);
}
count++;
if (count === array.length) {
finalCallback(_errs, _data);
}
});
}, i * delay);
}
}
答案 1 :(得分:0)
根据@thefourtheye的建议,您可以使用Promises
的概念,Bluebird是一个快速而好的库。 Promise.settle
可让您解决并拒绝您的承诺,然后检查结果。
function loopArray(array) {
var arrayOfPromises = [];
for (var i = 0; i < array.length; i++) {
arrayOfPromises.push(doSomethingAsync(array[i]));
}
Promise.settle(arrayOfPromises).then(function (results) {
console.log("All async calls done! You can inspect the result!");
console.log(results);
});
}
function doSomethingAsync(item) {
return new Promise(function(resolve, reject){
//Do you async work here!
console.log("Entering async function call " + item);
if(item === "three"){
reject("bad value!");
}
resolve(item + " promise done!");
});
}
loopArray(["one","two","three"]);
我制作了以下示例的JSFiddle。使用异步函数,promises可以帮助你很多,所以我真的建议你调查它。