zoukankan      html  css  js  c++  java
  • forEach与async/await使用踩坑

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

    思考如上代码、我们预期结果是先输出1,2,3,然后因为等待异步结果最后输出end

    但是实际上输出却是end先输出,才到1,2,3。

    原因如下:

    1、首先这是因为foreach是没有return返回值的(可以自己去跟下源码,foreach内部实现只是简单的回调)

    2、而foreach里面的回调函数因为加了async的原因,所以默认会返回一个promise,但是因为foreach的实现并没有返回值,所以导致返回的这个promise对象没人去管了

    首先为了保证end最后输出,我们肯定要先等待循环的返回结果因此改成如下代码

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

    但是这样改之后依然行不通,原因是foreach没有返回值,所以我们必须保证循环能够有返回值,所以要将foreach改成map

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

    结果依然不行,然后我们会发现其实map返回的并不是一个promise对象,而是一个包含promise对象的数组[promise, promise, promise],其中每个promise对象都是循环迭代产生的结果。而await是处理不了数组的,它只能处理promise对象。考虑到这一点我们基本上就差不多知道如何改正了、有两种方法。

    第一是将循环改成常规的遍历方式

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

    第二种就比较高端了,使用Promise.all(),这是一个专门处理promise数组的方法,当async标记的箭头函数返回一个promise对象时,map方法得到的就是一个promise对象数组,然后我们将这个数组丢给Promise.all()去依次执行,然后只需要使用await去等待执行结果,就能保证后面的end在得到结果后才会被输出,得到最终输出结果1,2,3,end

    async function test() {
     let arr = [1, 2, 3]
     await Promise.all(arr.map(async item => {
      const res = await fetch(item)
      console.log(res)
     }))
     console.log('end')
    }
  • 相关阅读:
    Codeforces Round #272 (Div. 2) A. Dreamoon and Stairs 水题
    Codeforces Round #368 (Div. 2) E. Garlands 二维树状数组 暴力
    Codeforces Round #368 (Div. 2) D. Persistent Bookcase 离线 暴力
    Codeforces Round #368 (Div. 2) C. Pythagorean Triples 数学
    Codeforces Round #368 (Div. 2) B. Bakery 水题
    Codeforces Round #368 (Div. 2) A. Brain's Photos 水题
    BZOJ 4636: 蒟蒻的数列 分块
    BZOJ 4610: [Wf2016]Ceiling Functi 水题
    设置让TortoiseGit记住账号和密码
    JSON.stringify转换Date不正确的解決方法
  • 原文地址:https://www.cnblogs.com/jiangxiaoxi/p/13672473.html
Copyright © 2011-2022 走看看