查看Async和underscore.js的异步分支,它会显示同步forEach
,map
和filter
的asyn版本。
考虑到Javascript是单线程的,返回一个有序,映射,forEached ...数组的值是什么值将返回的值传递给回调函数?
答案 0 :(得分:8)
当您对每个项目执行的操作依赖于底层异步任务时,这样的异步迭代函数非常有用。
例如,在Node.js中,文件系统操作是异步的(它们发生在一个单独的非JavaScript线程中,并在完成后调用回调)。例如,如果您希望将文件名列表映射到这些文件的信息,则在文件系统操作回调之前,您将无法将结果返回到映射。类似地,JavaScript数据库驱动程序往往是异步的(它们在另一个线程中工作,并在完成后回调一个JavaScript函数。)
例如,假设您有一个用户ID列表(如Stack Overflow问题中涉及的用户列表),并且您希望将它们映射到有关每个用户的详细信息。使用async.js
,可能如下所示:
async.map([2389, 6344, 27],
function(id, callback){
database.users.find({ id: id }, function(error, user){
if (error) {
callback(error);
} else {
callback(null, {
name: user.name,
reputation: user.reputation,
picture: user.picture
});
}
})
},
function(error, results){
/* results contains:
[
{ name: "Bob", reputation: 10, picture: "http://…" },
{ name: "Fred", reputation: 2910, picture: "http://…" },
{ name: "Steve", reputation: 25000, picture: "http://…" }
]
*/
}
);
将为数组中的每个项调用迭代器函数,并将启动数据库查询以获取有关该用户的详细信息。在开始下一个查询之前,它不会等待每个查询完成。数据库查询可能会很快完成,或者可能需要一段时间。如果它们是同步的,则它们一次只能运行一个。更糟糕的是,当数据库查询运行时,JavaScript线程将无法执行任何其他操作。
这样,数据库查询需要多长时间。当他们离开时,JavaScript线程可能处于空闲状态,或者可能没有处理其他事情(比如对服务器的另一个请求)。
当每个数据库请求完成时(并且它们甚至可能没有按照它们的启动顺序完成!),它会调用其回调函数,该函数将有关用户的信息放入对象并将其交给其< / em>回调。 async.js
跟踪到目前为止返回的迭代次数,并且只在每次迭代完成后调用最终回调。
您可以在async.js
文档中找到类似的示例。
在浏览器中,异步操作较少,但您可以使用async.js
对服务器的请求,加载一组资源(如脚本或图像)并确保它们都已成功加载或发送消息在窗户之间。