您的位置:首页 > 新闻 > 资讯 > javaScript的异步控制:async/await初试与进阶

javaScript的异步控制:async/await初试与进阶

2025/9/3 0:50:43 来源:https://blog.csdn.net/l_q_l/article/details/141785879  浏览:    关键词:javaScript的异步控制:async/await初试与进阶

作为有多年java皮毛式编程经验,python也能写几行的我,接触到javaScript之后居然觉得这是一门无法理解的语言,原因就在于它的异步处理。。我希望它按照我写的顺序执行,可是,它偏有自己的想法,使用console.log打印出来的执行顺序,总是让我无语。。。

以往都是通过.then(),昨天在同事的指导下,再次尝试async/await,居然成功了,而今天独自加班,就遇到了进阶需求,庆幸昨天学会了初阶。记录要点

初阶需求

上一篇自定义对话框组件中,当组件做完保存,需要通过emit通知父组件更新列表。我是这么写的:

onSave(){this.addUsrs();this.$emit("accountCreated");this.dialogVisible = false;
....
}

如你所想,addUsers中是一个后台保存的接口,所以,当父组件收到通知开始更新列表的时候,子组件的保存还正在执行呢,所以,父组件更新了个寂寞。。

修正方式1

.then()方法,将emit放到addUsers.then()中执行,具体可参考之前链式调用的博文,今天说说方法2.

修正方式2

1、将this.addUsers定义成一个async函数,其中使用await设置阻塞

//使用async,表示这是一个可以使用await控制执行顺序的同步函数
async addUsrs(){   //保存前的各种处理。。。。。。            await insertUsers(this.form.people);  //阻塞,执行保存结束后,才往下走this.$emit("accountCreated");    //重点:emit放到async函数里面来。走到这里的时候,上一步addUsers已经返回了
},

2、重点:把emit那一句放到addUsers里面来

只有在async函数内部,await才会等待返回后再执行下一步,如果emit还是像之前那样放置this.addUsers()后面,await是无法实现等待insert返回的。

如果emit那一句还是在onSave中,js的调用顺序大概是这样的:

1、执行onSave

2、执行addUsers,发现时间有点长,不等它,立刻返回

2、执行emit

3、父组件收到emit,开始更新列表。这时候addUsers有没有执行完,完全看运气。

如果emit在addUsers里面,js的调用顺序是这样的:

1、执行onSave

2、执行addUsers,发现时间有点长,不等它,立刻返回

2、执行dialogVisible = false,关闭对话框。

外层的主线执行完了,再看addUsers里面的支线

         2.1 执行insertUsers,发现时间有点长,但是前面有await,阻塞,等待执行完才返回

         2.2 insertUsers执行完返回,执行emit

         2.3 父组件收到通知,开始更新列表。

前面的序号,我分别用了两个2,不是笔误,表示这两个是同步执行的。可以看到,这里其实我们只是控制了emit一定要在insertUsers返回之后执行,其它的执行顺序,是不受我们控制的。而这个执行顺序,是按照函数的调用结构,层层返回的。我们只能控制某一层内的顺序,跨层的是无法控制的。

进阶需求:阻塞多接口

某页面created里面做初始化,一个数据需要同时使用两个接口的返回值,所以,我必须等两个接口都返回之后再做数据处理。但是,这两个接口之间是没有调用顺序的限制的,如果我使用链式调用虽然能实现功能,但是会影响效率。想到以前曾经听某项目在同事分析接口执行顺序的时候,提到过类似于接口1,接口2并发执行,返回后接口3和4顺序执行的说法。。于是,查了一下,果然有个阻塞多接口的方法:Promise.all()

方法1:await

async initProjectInfo(){const [fetch1Res,fetch2Res] = await Promise.all([fetchData1(this.projectFrm.unid),fetchData2(this.projectFrm.unid)]);//分别使用fetch1Res和fetch2Res进行数据处理.....}

方法2:then

initProjectInfo(){Promise.all([fetchData1(this.projectFrm.unid),fetchData2(this.projectFrm.unid)]).then(result => {const result1 = results[0];const result2 = results[1];// 合并两个数组const mergedUserList = [...result1, ...result2];// 输出或处理合并后的数组console.log(mergedUserList);
});}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com