array.map和for循环中的异步操作

时间:2020-08-16 14:08:10

标签: javascript arrays for-loop asynchronous

当我做这样的事情时,我意识到:

for (const entity of someArr) {
  console.log('start now!')
  await doSomeAsycAction()
  console.log('waited X secs!')
}

它打印出来:

start now!
waited X secs!
start now!
waited X secs!
...

但是当我使用地图时:

arr.map(async entity => {
  console.log('start now!')
  await doSomeAsycAction()
  console.log('waited X secs!')
})

它打印出来:

start now!
start now!
start now!
...
waited X secs!
waited X secs!
waited X secs!
...

有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:1)

这两个流程之间的区别在于,第一个流程(使用forfor..infor..of)按顺序运行循环迭代,而另一个流程(使用{{1} },mapfilterreduce等正在(如果在映射函数中的某处使用forEach符号的情况下)正在运行。 在async循环中,下一个迭代必须等待上一个迭代完成。这使您可以进行一些与下一次迭代相关的异步操作。 相反,使用async方法独立运行每个迭代,因此您不能依赖当前迭代中的其他迭代。这类函数将函数作为参数接收,并立即对数组中的每个项目执行该函数。

将每次迭代都视为独立的Promise执行。运行异步函数时,for符号表明此操作可能需要一段时间(即I / O,DB调用,网络操作...),并且让当前执行函数之外的代码继续进行(并且在异步调用返回后,稍后再恢复)。 await函数会看到当前迭代很忙,然后继续下一个迭代。将来会恢复并执行map

您可以使用console.log('waited X secs!')循环以这种方式模拟异步执行的相同行为(可能有助于证明两者之间的区别):

for

async-await语法在每个函数范围内都有效,for (const entity of someArr) { (async () => { console.log('start now!') await doSomeAsycAction() console.log('waited X secs!') })() } 定义了一个新的函数范围(该函数作为参数传递给该函数),就像在每次迭代中执行的(匿名)函数一样我的例子。希望对理解有所帮助。

要注意的重要一件事是map的每次迭代都不会返回您期望的映射值,而是一个可以用该值解决的承诺。因此,如果尝试依赖映射的数组值之一-必须在其前面添加一个map,否则该值类型仍然是一个保证。看下面的例子:

await

答案 1 :(得分:-2)

基本数组原型循环函数(例如forEach,map,filter,find等)不等待下一次迭代。它们的基本行为是迭代不等待。如果要使用类似等待功能,请尝试使用以下类似方式

for (const event of events) {
  if (failure or conditional) {   
    continue;
  } 
}