Javascript 在阵列(或OBJ)上迭代异步的最聪明/最干净的方法是什么?
我就是这样做的:Javascript 在阵列(或OBJ)上迭代异步的最聪明/最干净的方法是什么?,javascript,node.js,Javascript,Node.js,我就是这样做的: function processArray(array, index, callback) { processItem(array[index], function(){ if(++index === array.length) { callback(); return; } processArray(array, index, callback); }); };
function processArray(array, index, callback) {
processItem(array[index], function(){
if(++index === array.length) {
callback();
return;
}
processArray(array, index, callback);
});
};
function processItem(item, callback) {
// do some ajax (browser) or request (node) stuff here
// when done
callback();
}
var arr = ["url1", "url2", "url3"];
processArray(arr, 0, function(){
console.log("done");
});
有什么好处吗?如何避免那些意大利面条式的代码 签出该库,它是为控制流(异步内容)而设计的,并且它有很多用于数组内容的方法:each、filter、map。查看github上的文档。以下是您可能需要的:
每个(arr、迭代器、回调)
将迭代器函数并行应用于数组中的每个项。迭代器由列表中的一个项和完成时的回调调用。如果迭代器将错误传递给此回调,则会立即调用每个
函数的主回调并显示错误
每个系列(arr、迭代器、回调)
与
每个
相同,仅迭代器应用于串联数组中的每个项。下一个迭代器仅在当前迭代器完成处理后调用。这意味着迭代器函数将按顺序完成。正如正确指出的,您必须使用setTimeout,例如:
each_async = function(ary, fn) {
var i = 0;
-function() {
fn(ary[i]);
if (++i < ary.length)
setTimeout(arguments.callee, 0)
}()
}
each_async([1,2,3,4], function(p) { console.log(p) })
each_async=函数(ary,fn){
var i=0;
-函数(){
fn(ari[i]);
if(++i
正如某些答案所指出的,可以使用“异步”库。但有时您只是不想在代码中引入新的依赖项。下面是另一种方法,可以循环并等待一些异步函数的完成
var items = ["one", "two", "three"];
// This is your async function, which may perform call to your database or
// whatever...
function someAsyncFunc(arg, cb) {
setTimeout(function () {
cb(arg.toUpperCase());
}, 3000);
}
// cb will be called when each item from arr has been processed and all
// results are available.
function eachAsync(arr, func, cb) {
var doneCounter = 0,
results = [];
arr.forEach(function (item) {
func(item, function (res) {
doneCounter += 1;
results.push(res);
if (doneCounter === arr.length) {
cb(results);
}
});
});
}
eachAsync(items, someAsyncFunc, console.log);
现在,运行
节点iterasync.js
将等待大约三秒钟,然后打印['1','2','3']
。这是一个简单的示例,但可以扩展到处理许多情况。处理数组(或任何其他iterable)的异步迭代的最简单方法是使用wait运算符(仅在异步函数中)和for of循环
(异步函数(){
for(让[0,1]的值){
值+=等待(承诺.解决(1))
console.log(值)
}
})()
在现代JavaScript中,有一些有趣的方法可以将数组扩展为异步itarable对象
在这里,我想展示一个全新类型AsyncArray
的框架,它继承了Array
类型的优点,将其扩展为一个asyncIterable数组
这仅适用于现代发动机。下面的代码使用了最新的技巧,如和
如果您不熟悉这些主题,我建议您提前查看上述链接主题
class AsyncArray extends Array {
#INDEX;
constructor(...ps){
super(...ps);
if (this.some(p => p.constructor !== Promise)) {
throw "All AsyncArray items must be a Promise";
}
}
[Symbol.asyncIterator]() {
this.#INDEX = 0;
return this;
};
next() {
return this.#INDEX < this.length ? this[this.#INDEX++].then(v => ({value: v, done: false}))
: Promise.resolve({done: true});
};
};
使用jQuery,可以使用
$.each([…],function(){…})在其他JS库中也会有类似的方法。是的,但它们是同步的。Aron正在询问异步循环,这是一个更有趣的问题!2016年,我今天用了这个。也许应该看看ES6,但是。。。谢谢为什么在第二个函数()
之前有一个“-”(减号)?@AaronDigulla-function()
导致立即数函数被视为一个表达式。它实际上与将函数包装在括号中没有任何区别,这是使其成为有效表达式的另一种方法。请参阅:函数名为“each”和“eachSeries”,请记住,他的注释是在您的注释之前两年写的,尽管@LaurentDebriconhow您如何在数组上无限循环,例如async.eachSeries([1,2,3]),我想在3之后返回1,如何做到这一点令人难以置信的是,这个答案在这条评论中的得票率为零。伟大的解决方案!输出不一定是1,2,3顺序。不处理空数组的情况,计数器似乎不必要,因为您有“results”的长度。我发现这种方法更干净。