S循环中使用async、await的正确姿势

  • Post author:
  • Post category:其他


概览(循环方式 – 常用)

  • for
  • map
  • forEach
  • filter

声明遍历的数组和异步方法

声明一个数组:⬇️

const skills = ['js', 'vue', 'node', 'react']
复制代码

再声明一个

promise

的异步代码: ⬇️

function getSkillPromise (value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value)
    }, 1000)
  })
}
复制代码

for 循环中使用

由于

for

循环并非函数,而

async



await

需要在函数中使用,因此需要在

for

循环外套一层

function

async function test () {
  for (let i = 0; i < skills.length; i++) {
    const skill = skills[i]
    const res = await getSkillPromise(skill)
    console.log(res)
  }
}

test() // 调用
复制代码

当使用

await

时,希望JavaScript暂停执行,直到等待 promise 返回处理结果。上述结果意味着

for

循环中有异步代码,是可以等到

for

循环中异步代码完全跑完之后再执行

for

循环后面的代码。

但是他不能处理回调的循环,如

forEach



map



filter

等,下面具体分析。

map 中使用



map

中使用

await

,

map

的返回值始是

promise

数组,这是因为异步函数总是返回

promise

async function test () {
  console.log('start')
  const res = skills.map(async item => {
    return await getSkillPromise(item)
  })
  console.log(res)
  console.log('end')
}

test()
复制代码

结果:始终为

promise

数组

start
[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]
end
复制代码

若果你想要等到

promise

的返回结果,可以使用

promise.all()

处理一下

async function test () {
  console.log('start')
  const res = skills.map(async item => {
    return await getSkillPromise(item)
  })
  const resPromise = await Promise.all(res)
  console.log(resPromise)
  console.log('end')
}

test()

// 结果
start
[ 'js', 'vue', 'node', 'react' ]
end

复制代码

forEach 中使用

先上代码和结果

async function test () {
  console.log('start')
  skills.forEach(async item => {
    const res = await getSkillPromise(item)
    console.log(res)
  })
  console.log('end')
}

test()
复制代码

预期结果

'Start'
'js'
'vue'
'node'
'react'
'End'
复制代码

实际结果 在

forEach

循环等待异步结果返回之前就执行了

console.log('end')

'Start'
'End'
'js'
'vue'
'node'
'react'
复制代码

JavaScript 中的

forEach

不支持 promise 感知,也支持

async



await

,所以不能在

forEach

使用

await

filter 中使用

使用

filter

过滤

item



vue

或者

react

的选项

正常使用

filter

async function test () {
  console.log('start')
  const res = skills.filter(item => {
    return ['vue', 'react'].includes(item)
  })
  console.log(res)
  console.log('end')
}

test() // 调用

// 结果
start
[ 'vue', 'react' ]
end
复制代码

使用

await

后:

async function test () {
  console.log('start')
  const res = skills.filter(async item => {
    const skill = await getSkillPromise(item)
    return ['vue', 'react'].includes(item)
  })
  console.log(res)
  console.log('end')
}

test()
复制代码

预期结果:

start
[ 'vue', 'react' ]
end
复制代码

实际结果:

[ 'js', 'vue', 'node', 'react' ]
end
复制代码

结论:因为异步函数

getSkillPromise

返回结果返回的

promise

总是真的,所以所有选项都通过了过滤