记录arr.map 和arr.foreach 遇到的回调函数(异步和同步问题)的坑

大体问题是:
经过map或者foreach循环的回调函数操做数组,回调函数内部有ajax异步函数,经过await同步的写法来调用的。console.log打印出数组跟实际渲染到view层的页面始终不一致。
后来改写成for循环就行了。ajax

第一次发现bug觉得是双向绑定出现了问题,由于数组会有此状况。但后来排除了。api

第二次发现是只要经过await调用了异步方法,后面同步代码再执行await后返回的结果,就会出现bug。数组

第三次。。。隐藏各类代码,还怀疑是阿里云的sdk出现了问题。
后来找老大才解决了这个问题,虽然上厕所期间也感受就是map或foreach方法的回调函数出现了问题,但不知道从何改也想过使用for循环改造,but须要在for循环内部使用await关键字,考虑可能会报错。异步

因此总结出来,基础知识,在理解map和foreach这个api不够深入,也对await 关键词的使用场景理解不透彻(虽然是for循环,但做用域函数能够找到顶层的函数做用域,因此不会报错)async

贴出代码:函数

错误代码oop

adBannerList.map(async (item) => {
              // 异步函数 转同步的写法
              let res = await this.getAliyunAds();
              // 异步函数执行成功后,改变此数组的值
              item.imageUrl = res.imgUrl;
              item.linkUrl = res.actUrl;
          })
          // map 循环结束后,再执行双向绑定
          this.setData({
            bannerList: adBannerList,
          });
         console.log('bannerList', this.data.bannerList)

指望结果是map循环结束后,才会执行双向绑定setData函数。
实际结果是:还未等map循环完(还未等内部的await 后面的异步函数执行完),setData 就执行了。
此时console.log 数组所看见的结果,跟view渲染呈现的结果不一致。
这里须要去深刻理解下,引用类型和简单类型的console.log,以及console.log的机制。
推荐看这篇文章:console.log碰见的坑this

正确代码:阿里云

for(let i = 0;i < adBannerList.length; i++) {
              let item = adBannerList[i]
              // 这里await关键词能够用是由于for循环内部没函数做用域,
              //因此会向上找函数做用域,只要有async就能够。
              let res = await this.getAliyunAds();
              item.imageUrl = res.imgUrl;
              item.linkUrl = res.actUrl;
          }
          
          this.setData({
            bannerList: adBannerList,
          });

知识点总结:
1.map和foreach(应该还有更多的相似函数)的回调函数是一个同步函数,非异步函数。.net

须要升入的知识点:
一、console.log的机制。尤为是针对引用类型
二、async await使用场景?在何时会失效?
三、类型map和foreach 这样的循环函数机制。


我后来又从新去作了一个demo,发现问题的所在点多是:
回调函数内部有ajax异步函数,经过await同步的写法来调用的
重点就是:await 后面执行的函数是ajax异步函数。
那若是await后面执行的函数是setTimeout 函数呢?

贴代码:

function test () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('-----')
        }, 3000)
      })
    }

    function async lnk() {
      for(let i = 0; i < arr.length; i++ ){
         await test()
      }
      console.log('arr', arr) 
    }
    lnk()

按照刚才的理解,for循环内部执行await方法,按理是应该阻塞执行,等待异步执行后,再执行同步console.log('arr', arr)方法。但实际是:先执行了打印arr,而后3秒后执行的test内部方法。一样看似形成了await的“失效”我如今完全懵逼了,得去恶补下eventloop的知识点了。不太重点应该仍是await--async 这一堆api理解不够。

相关文章
相关标签/搜索