我就是这么做的:
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");
});
它有什么好处吗?如何避免那些意大利面条般的代码?
6条答案
按热度按时间apeeds0o1#
检查async库,它是为控制流(异步填充)而设计的,它有很多用于数组填充的方法:each,filter,map.查看github上的文档.下面是你可能需要的:
each(arr、迭代器、回调)
将迭代器函数并行应用于数组中的每一项。使用列表中的项和完成时的回调调用迭代器。如果迭代器将错误传递给此回调,则立即使用该错误调用
each
函数的主回调。每个序列(arr、迭代器、回调)
与
each
相同,只是迭代器被应用于数组中的每一项,下一个迭代器只在当前迭代器完成处理后才被调用,这意味着迭代器函数将按顺序完成。dw1jzc5e2#
正如在一些答案中指出的,你可以使用“异步”库。但是有时候你只是不想在你的代码中引入新的依赖。下面是另一种方法,你可以循环并等待一些异步函数的完成。
现在,运行
node iterasync.js
将等待大约3秒钟,然后打印[ 'ONE', 'TWO', 'THREE' ]
,这是一个简单的示例,但可以扩展以处理许多情况。zphenhs43#
正如正确指出的那样,您必须使用setTimeout,例如:
wr98u20j4#
处理数组(或任何其他可迭代对象)异步迭代的最简单方法是使用await操作符(仅在异步函数中)和for of循环。
你可以使用一个库来转换你可能需要的任何函数,这些函数接受回调来返回承诺。
bq3bfh9z5#
在现代JavaScript中,有一些有趣的方法可以将Array扩展为可异步转换的对象。
这里我想演示一个全新类型
AsyncArray
的框架,它通过继承Array
类型的优点来扩展Array
类型,使其成为一个异步可迭代数组。这只在现代引擎中可用。下面的代码使用了最新的噱头,如私有示例字段和
for await...of
。如果你不熟悉他们,那么我建议你提前看看上面链接的主题。
所以一个异步迭代数组必须包含承诺。只有这样它才能返回一个迭代器对象,每个
next()
调用返回一个承诺,最终resolve
到一个像{value : "whatever", done: false}
或{done: true}
这样的对象。所以基本上这里返回的所有东西都是一个承诺。await
抽象解包其中的值,并把它给我们。正如我之前提到的,这个
AsyncArray
类型是从Array
扩展而来的,它允许我们使用我们熟悉的Array方法,这将简化我们的工作。让我们看看会发生什么
8ulbf1ek6#
对于现代的Node.js:
要真正异步地迭代集合,你可以试试我的tiny包,它没有依赖关系,与ESM和CJS模块兼容,使用.d.ts类型,检查代码,它真的很小。
https://www.npmjs.com/package/array-to-async-iterable
您可以像这样使用它:
由于JavaScript引擎的微任务和宏任务特性,不能只使用
for await of
循环。简单地说,使用以下代码,您将无法获得新的HTTP请求,也无法让其他定时器的回调执行:你强迫V8或其他引擎执行所有的微任务(循环迭代),当循环完成时,你将解除阻塞事件循环,并准备好接收HTTP连接,所以这段代码完全无用。