JavaScript异步任务(promise、async/await、settimeout)执行顺序

promise、async/await、settimeout等异步任务都已经非常熟悉,但是这三者混合起来执行的话执行顺序却是看得一头雾水。阅读本文之前应该对Promise、async/await以及异步队列中的宏任务和微任务有所了解。

首先上一段代码:

async function async1() {
	console.log("async1 start");
	await  async2();
	console.log("async1 end");

}
async  function async2() {
	console.log( 'async2');
}
console.log("script start");
setTimeout(function () {
	console.log("settimeout");
},0);
async1();
new Promise(function (resolve) {
	console.log("promise1");
	resolve();
}).then(function () {
	console.log("promise2");
});
console.log('script end');

正确答案如下:

script start
async1 start
async2
promise1
script end
async1 end
promise2
settimeout

这次我就不讲解错误答案以及错误的原因了,直接对代码分析为什么会造成这样的结果。

  • console.log(“script start”):这个是同步任务,立即输出script start这个应该没有什么问题
  • setTimeout(function () {console.log(“settimeout”);},0):这个setTimeout方法是异步任务,而且是属于异步中的宏任务,所以是最后执行的
  • async1():同步执行async1函数,但是async1函数中存在await async2(),所以async2函数执行,async2函数后面的代码都放到异步队列中
  • new Promise:Promise对象中的代码是同步执行的,then方法才是进入异步队列处理的。
  • console.log(‘script end’):同步任务,直接执行。

所以综上所述,可以得出前面几个输出结果

script start–>async1 start–>async2–>promise1–>script end

对于Promise为什么是一部分同步一部分异步,async函数为什么执行中跳出。如果你产生这样的疑问,请看这里:

接下来是异步队列中的执行分析:

  • setTimeout(function () {console.log(“settimeout”);},0):定时函数setTimeout属于异步宏任务,放到最后执行,上面说过了。
  • console.log(“async1 end”):由于await async2()的原因console.log(“async1 end”)被放到异步队列,而且await async2()的执行是立刻完成的,所以console.log(“async1 end”)实际上是排到异步队列的第一位,在所有同步任务执行完之后立刻执行
  • console.log(“promise2”):由于代码中的Promise对象放在async1()之后,所以对应的Promise对象的then方法在异步队列中排序则排到console.log(“async1 end”)之后,排在异步队列的第二位
  • 最后,你是不是忘了什么?前面一直提到setTimeout,由于他是异步任务中的宏任务,所以被放在微任务结束之后执行

所以异步任务的执行结果为:

async1 end–>promise2–>settimeout

将同步任务和异步任务合并则可以得出:

script start–>async1 start–>async2–>promise1–>script end–>async1 end–>promise2–>settimeout

课后训练?

分析下面程序运行的结果:

async function async1() {
	console.log("async1 start");
	await  async2();
	console.log("async1 end");

}
async  function async2() {
	console.log( 'async2');
	return new Promise(function(resolve){
		setTimeout(function(){
			console.log("new async2");
			resolve();
		},1000)
	})
}
console.log("script start");
setTimeout(function () {
	console.log("settimeout");
},0);
async1();
new Promise(function (resolve) {
	console.log("promise1");
	resolve();
}).then(function () {
	console.log("promise2");
});
console.log('script end');

自己要是想要答案的话放到console去执行一下就知道啦!

发表评论

电子邮件地址不会被公开。 必填项已用*标注