大体问题是:
经过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理解不够。