重学 JS:为啥 await 不能用在 forEach 中详解


Posted in Javascript onApril 15, 2019

这是重学 JS 系列的第三篇文章,写这个系列的初衷也是为了夯实自己的 JS 基础或者了解一些之前不知道的东西。既然是重学,肯定不会从零开始介绍一个知识点,如有遇到不会的内容请自行查找资料。

不知道你有没有写过类似的代码,反正以前我是写过

function test() {
 let arr = [3, 2, 1]
 arr.forEach(async item => {
  const res = await fetch(item)
  console.log(res)
 })
 console.log('end')
}

function fetch(x) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve(x)
  }, 500 * x)
 })
}

test()

我当时期望的打印顺序是

3
2
1
end

 结果现实与我开了个玩笑,打印顺序居然是

end
1
2
3

为什么?

其实原因很简单,那就是 forEach 只支持同步代码。

我们可以参考下 Polyfill 版本的 forEach,简化以后类似就是这样的伪代码

while (index < arr.length) {
  // 也就是我们传入的回调函数
  callback(item, index)
}

从上述代码中我们可以发现,forEach 只是简单的执行了下回调函数而已,并不会去处理异步的情况。并且你在 callback 中即使使用 break 也并不能结束遍历。

怎么解决?

一般来说解决的办法有两种。

第一种是使用 Promise.all 的方式

async function test() {
 let arr = [3, 2, 1]
 await Promise.all(
  arr.map(async item => {
   const res = await fetch(item)
   console.log(res)
  })
 )
 console.log('end')
}

这样可以生效的原因是 async 函数肯定会返回一个 Promise 对象,调用 map 以后返回值就是一个存放了 Promise 的数组了,这样我们把数组传入 Promise.all 中就可以解决问题了。但是这种方式其实并不能达成我们要的效果,如果你希望内部的 fetch 是顺序完成的,可以选择第二种方式。

第一种方法是使用 for...of

async function test() {
 let arr = [3, 2, 1]
 for (const item of arr) {
  const res = await fetch(item)
  console.log(res)
 }
 console.log('end')
}

这种方式相比 Promise.all 要简洁的多,并且也可以实现开头我想要的输出顺序。

但是这时候你是否又多了一个疑问?为啥 for...of 内部就能让 await 生效呢。

因为 for...of 内部处理的机制和 forEach 不同,forEach 是直接调用回调函数,for...of 是通过迭代器的方式去遍历。

async function test() {
 let arr = [3, 2, 1]
 const iterator = arr[Symbol.iterator]()
 let res = iterator.next()
 while (!res.done) {
  const value = res.value
  const res1 = await fetch(value)
  console.log(res1)
  res = iterator.next()
 }
 console.log('end')
}

最后
以上就是本篇文章的全部内容了,如果你还有什么疑问欢迎在评论区与我互动。

我所有的系列文章都会在我的 Github 中最先更新,有兴趣的可以关注下。今年主要会着重写以下三个专栏

重学 JS
React 进阶
重写组件

以上所述是小编给大家介绍的为啥await 不能用在 forEach 中详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript 的继承
Oct 01 Javascript
调用innerHTML之后onclick失效问题的解决方法
Jan 28 Javascript
js加载读取内容及显示与隐藏div示例
Feb 13 Javascript
jQuery中:contains选择器用法实例
Dec 30 Javascript
director.js实现前端路由使用实例
Feb 03 Javascript
jquery插件validation实现验证身份证号等
Jun 04 Javascript
jQuery实现简单的网页换肤效果示例
Sep 18 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
Sep 28 Javascript
简述vue状态管理模式之vuex
Aug 29 Javascript
element-ui的回调函数Events的用法详解
Oct 16 Javascript
解决Vue打包后访问图片/图标不显示的问题
Jul 25 Javascript
解决vue更新路由router-view复用组件内容不刷新的问题
Nov 04 Javascript
你不知道的Vue技巧之--开发一个可以通过方法调用的组件(推荐)
Apr 15 #Javascript
详解JavaScript中的强制类型转换
Apr 15 #Javascript
一个小时快速搭建微信小程序的方法步骤
Apr 15 #Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 #Javascript
ES6知识点整理之模块化的应用详解
Apr 15 #Javascript
详解如何运行vue项目
Apr 15 #Javascript
vue单页面在微信下只能分享落地页的解决方案
Apr 15 #Javascript
You might like
PHP mysql事务问题实例分析
2016/01/18 PHP
PHP MSSQL 分页实例
2016/04/13 PHP
PHP十六进制颜色随机生成器功能示例
2017/07/24 PHP
用javascript实现给图片加链接
2007/08/15 Javascript
javascript显示隐藏层比较不错的方法分析
2008/09/30 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
transport.js和jquery冲突问题的解决方法
2015/02/10 Javascript
浅谈jQuery中Ajax事件beforesend及各参数含义
2016/12/03 Javascript
BootStrap中
2016/12/10 Javascript
JavaScript中校验银行卡号的实现代码
2016/12/19 Javascript
JS简单获取当前年月日星期的方法示例
2017/02/07 Javascript
jQuery插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
2017/03/23 jQuery
Vue一次性简洁明了引入所有公共组件的方法
2018/11/28 Javascript
node实现生成带参数的小程序二维码并保存到本地功能示例
2018/12/05 Javascript
vue+iview 兼容IE11浏览器的实现方法
2019/01/07 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
JavaScript代理模式原理与用法实例详解
2020/03/10 Javascript
Paypal支付不完全指北
2020/06/04 Javascript
JQuery基于FormData异步提交数据文件
2020/09/01 jQuery
[00:35]可解锁地面特效
2018/12/20 DOTA
python实现telnet客户端的方法
2015/04/15 Python
python使用xlrd与xlwt对excel的读写和格式设定
2017/01/21 Python
python利用ffmpeg进行录制屏幕的方法
2019/01/10 Python
用python求一个数组的和与平均值的实现方法
2019/06/29 Python
sklearn+python:线性回归案例
2020/02/24 Python
基于python实现模拟数据结构模型
2020/06/12 Python
基于tf.shape(tensor)和tensor.shape()的区别说明
2020/06/30 Python
中软国际Java程序员笔试题
2014/07/19 面试题
数控专业个人求职信范例
2013/11/29 职场文书
校友会欢迎辞
2014/01/13 职场文书
《飞向蓝天的恐龙》教学反思
2014/04/09 职场文书
高一课前三分钟演讲稿
2014/09/13 职场文书
2014领导班子“四风问题”对照检查材料思想汇报(执法局)
2014/09/21 职场文书
医生个人自我剖析材料
2014/10/08 职场文书
家长通知书家长意见
2015/06/03 职场文书
对讲机的最大通讯距离是多少
2022/02/18 无线电