耀极客论坛

 找回密码
 立即注册
查看: 517|回复: 0

JS循环中正确使用async、await的姿势分享

[复制链接]

336

主题

318

帖子

22万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
220555
发表于 2022-5-9 00:57:46 | 显示全部楼层 |阅读模式
  async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案,下面这篇文章主要给大家介绍了关于JS循环中正确使用async、await的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

概览(循环方式 - 常用)
       
  • for   
  • map   
  • forEach   
  • filter

声明遍历的数组和异步方法
  声明一个数组:⬇️
  1. const skills = ['js', 'vue', 'node', 'react']
复制代码
  再声明一个promise的异步代码: ⬇️
  1. function getSkillPromise (value) {
  2.   return new Promise((resolve, reject) => {
  3.     setTimeout(() => {
  4.       resolve(value)
  5.     }, 1000)
  6.   })
  7. }
复制代码
for 循环中使用
  由于for循环并非函数,而async、await需要在函数中使用,因此需要在for循环外套一层function
  1. async function test () {
  2.   for (let i = 0; i ‹ skills.length; i++) {
  3.     const skill = skills[i]
  4.     const res = await getSkillPromise(skill)
  5.     console.log(res)
  6.   }
  7. }
  8. test() // 调用
复制代码

  当使用await时,希望JavaScript暂停执行,直到等待 promise 返回处理结果。上述结果意味着for循环中有异步代码,是可以等到for循环中异步代码完全跑完之后再执行for循环后面的代码。
  但是他不能处理回调的循环,如forEach、map、filter等,下面具体分析。

map 中使用
  在map中使用await, map 的返回值始是promise数组,这是因为异步函数总是返回promise。
  1. async function test () {
  2.   console.log('start')
  3.   const res = skills.map(async item => {
  4.     return await getSkillPromise(item)
  5.   })
  6.   console.log(res)
  7.   console.log('end')
  8. }
  9. test()
复制代码
  结果:始终为promise数组
  1. start
  2. [
  3.   Promise { ‹pending> },
  4.   Promise { ‹pending> },
  5.   Promise { ‹pending> },
  6.   Promise { ‹pending> }
  7. ]
  8. end
复制代码
  若果你想要等到promise的返回结果,可以使用promise.all()处理一下
  1. async function test () {
  2.   console.log('start')
  3.   const res = skills.map(async item => {
  4.     return await getSkillPromise(item)
  5.   })
  6.   const resPromise = await Promise.all(res)
  7.   console.log(resPromise)
  8.   console.log('end')
  9. }
  10. test()
  11. // 结果
  12. start
  13. [ 'js', 'vue', 'node', 'react' ]
  14. end
复制代码
forEach 中使用
  先上代码和结果
  1. async function test () {
  2.   console.log('start')
  3.   skills.forEach(async item => {
  4.     const res = await getSkillPromise(item)
  5.     console.log(res)
  6.   })
  7.   console.log('end')
  8. }
  9. test()
复制代码
  预期结果
  1. 'Start'
  2. 'js'
  3. 'vue'
  4. 'node'
  5. 'react'
  6. 'End'
复制代码
  实际结果 在forEach循环等待异步结果返回之前就执行了console.log('end')
  1. 'Start'
  2. 'End'
  3. 'js'
  4. 'vue'
  5. 'node'
  6. 'react'
复制代码
  JavaScript 中的 forEach不支持 promise 感知,也支持 async 和await,所以不能在 forEach 使用 await 。

filter 中使用
  使用filter过滤item为vue或者react的选项
  正常使用 filter:
  1. async function test () {
  2.   console.log('start')
  3.   const res = skills.filter(item => {
  4.     return ['vue', 'react'].includes(item)
  5.   })
  6.   console.log(res)
  7.   console.log('end')
  8. }
  9. test() // 调用
  10. // 结果
  11. start
  12. [ 'vue', 'react' ]
  13. end
复制代码
  使用 await后:
  1. async function test () {
  2.   console.log('start')
  3.   const res = skills.filter(async item => {
  4.     const skill = await getSkillPromise(item)
  5.     return ['vue', 'react'].includes(item)
  6.   })
  7.   console.log(res)
  8.   console.log('end')
  9. }
  10. test()
复制代码
  预期结果:
  1. start
  2. [ 'vue', 'react' ]
  3. end
复制代码
  实际结果:
  1. [ 'js', 'vue', 'node', 'react' ]
  2. end
复制代码
  结论:因为异步函数getSkillPromise返回结果返回的promise总是真的,所以所有选项都通过了过滤

附使用小结
       
  • 如果你想连续执行await调用,请使用for循环(或任何没有回调的循环)。   
  • 永远不要和forEach一起使用await,而是使用for循环(或任何没有回调的循环)。   
  • 不要在 filter 和 reduce 中使用 await,如果需要,先用 map 进一步骤处理,然后在使用 filter 和 reduce 进行处理。
  结语:由于工作中遇到了超大表单抽离组件,异步校验是遇到了此问题,后来经过查阅资料总结出来的结果

总结
  到此这篇关于JS循环中正确使用async、await的文章就介绍到这了,更多相关JS循环中使用async、await内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-12-7 12:08 , Processed in 0.078609 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表