JS循环中使用async、await的正确姿势
转载
概览(循环方式 - 常用)
声明遍历的数组和异步方法
声明一个数组:⬇️
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
总是真的,所以所有选项都通过了过滤