当前位置: 首页 > Web前端 > HTML5

你可能忽略了的async-await问题

时间:2023-04-05 11:09:04 HTML5

async/await想必大家都用过,在处理异步操作的时候真的很方便。如果有不熟悉的朋友,可以看看作者之前的文章:带你了解async/await。今天主要说一下使用async/await时容易忽略和出错的一些事情。示例这是一个常见的Vue代码片段:asyncinitStore(query){awaitthis.getConfig();等待this.getUser();等待this.checkRussianContext(查询);等待this.getBasket(this.$store.state.config.selectedCurrency),awaitthis.$store.dispatch('options/fetchOptions',{basket:this.$store.state.basket,});},在上面的代码中,每一行都会等待上一行的结果返回后执行。例如getUser会等待getConfig数据返回后再执行。在看这段代码的时候,需要注意以下几点:如果某行的执行不需要上一行的数据怎么办?为什么阻塞代码会减慢整个应用程序的速度?我们可以让所有不相关的方法一起执行吗?喜欢使用Promise.all?是否可以使用then链接相关方法以避免阻塞其余代码?本文的重点是通过分析async/await可能导致的问题,帮助您发现代码不良味道。不相关的请求应该并行执行。我们来看一些具体数据下的情况。以下是示例代码:constgetUserData=async()=>{//随机获取一张狗图片作为头像constres=awaitfetch('https://dog.ceo/api/breeds/image/random')const{message}=awaitres.json()//获取随机生成的用户信息constuser=awaitfetch('https://randomuser.me/api/')const{results}=awaituser.json()//...}上面的代码在fast3G下执行了100次(使用Chrome开发者工具),平均执行时间为1231.10ms但是很明显,第二次请求不需要第一次请求的结果,所以我们修改成以下代码并执行100次:constgetUserDataFaster=async()=>{//两个请求并行执行const[res,user]=awaitPromise.all([fetch('https://dog.ceo/api/breeds/image/random'),fetch('https://randomuser.me/api/')])const[{message},{results}]=awaitPromise.all([res.json(),user.json()])//...}我们得到的平均执行时间为612.50毫秒,几乎是一半的时间。要点:尽量并行执行查询请求。你可以使用本codepen中的代码来体验不相关的代码你不必再等待示例:asyncinitStore(query){awaitPromise.all([this.getConfig(),this.getUser(),this.checkRussianContext(查询)])等待this.getBasket(this.$store.state.config.selectedCurrency),awaitthis.$store.dispatch('options/fetchOptions',{basket:this.$store.state.basket,});awaitinitBooking()},前面三个请求是并行执行的,而接下来的一段代码依赖于前面获取到的数据,所以需要在后面执行,但是大家有没有发现什么问题呢?在getBasket和fetchOptions完成之前,initBooking的缺点是无法执行,即使它不需要来自这两个方法的任何数据。一个简单的解决方案是使用await而不是.then:这个用法见开头的另一篇文章asyncinitStore(query){awaitPromise.all([this.getConfig(),this.getUser(),this.checkRussianContext(查询)])this.getBasket(this.$store.state.config.selectedCurrency).then(async()=>{awaitthis.$store.dispatch('options/fetchOptions',{basket:this.$store.state.basket,});})awaitinitBooking()},在这种情况下,getBasket和initBooking都可以并行执行。结束语async/await是JavaScript中的一个很棒的特性,在我们享受它们带来的便利的同时,我们也需要意识到它们可能带来的问题。有机会检查一下你的代码,看看有没有可以并行运行的代码块~感谢阅读~参考链接Thedangersofasync/await