关于JS任务执行顺序-宏任务微任务的理解

一 、概念

了解JS任务执行顺序之前,先了解几个概念

1.同步任务和异步任务的由来

由于JS是单线程,在代码执行的时候,如果代码顺序执行,当前一段代码执行需要很长一段时间,就会影响后面代码的执行,带来的后果可能就是代码执行效率低,页面卡顿,用户体验差,为了避免这个问题,就出现了异步编程,通过回调函数来存放和执行异步代码,任务也划分为两种:同步任务和异步任务。

2.同步任务,异步任务的解释

2.1同步任务:即主线程上的任务,按照顺序由上至下依次执行,当前一个任务执行完毕后,才能执行下一个任务。
2.2异步任务:不进入主线程,而是进入任务队列的任务,当主线程上的任务执行完后,才会执行任务队列里的任务,异步任务又分为宏任务和微任务

3.宏任务和微任务

宏任务:script(整体代码)、setTimeout、setInterval、setImmediate(Node.js 环境)、UI事件、I/O(Node.js)
微任务:promise中的.then和.catch,process.nextTick()

二、执行顺序的理解

通过实例来帮助理解js的执行顺序

console.log('script start')     //1
async function async1() {		//2
  await async2()				//3
  console.log('async1 end')		//4
}		//5
async function async2() {		//6
  console.log('async2 end')		//7
}								//8
async1()		//9
setTimeout(function() {		//10
  console.log('setTimeout')		//11
}, 0)		//12
new Promise(resolve => {		//13
  console.log('Promise')		//14
  resolve()		//15
})		//16
  .then(function() {		//17
    console.log('promise1')		//18
  })		//19
  .then(function() {		//20
    console.log('promise2')		//21
  })		//22
console.log('script end')		//23

这是一道经典的考察js执行顺序的面试题,后面注释了行数,一步一步来分解
1.执行主线程上的同步代码,先打印第一行的script start,然后2-8行是声明的两个函数
2.执行主线程上的同步代码,第九行,是一个函数调用,进入async1内部,async1其实是声明了一个promise,
promise是同步代码,会顺序执行打印async2 end,只有.then里面的代码会加入微任务队列里,这里相当于执行了async2()之后,再将第四行代码加入一个微任务队列中
3.回主线程中,遇到setTimeout(),加入到宏任务队列
4.主线程继续往后执行,前面说过,promise是同步代码,.then后面的回调会加入微任务队列,所以会打印14行的Promise
5.继续主线程,打印23行的script end
6.主线程执行完成,开始执行微任务队列内的任务,遵循先进先出的原则,依次打印第四行的async1 end,第18行的promise1,第21行的promise2
7.微任务执行结束,开始执行宏任务setTimeout,打印11行的setTimeout
所以最终执行顺序为:

	script start - 1
	async2 end - 7
	promise -14
	script end - 23
	async1 end -4
	promise1 - 18
	promise2 - 21
	setTimeout -11

执行顺序的总结:
1.主线程上的同步任务可以看做第一个宏任务,先执行主线程上的同步任务,将异步任务放入队列,宏任务放入下一个宏任务队列,微任务放入微任务队列,当主线程任务执行完成之后,就按照先进先出的原则执行所有的微任务,微任务执行完成后,开始执行下一个宏任务队列
2.当一个宏任务执行完成,如果微任务队列有微任务,会执行完所有微任务,再执行下一个宏任务
3.promise不属于微任务,只是promise.then()和.catch()才属于微任务
4.简单记法:主线程同步任务 = promise > promise.then() > setTimeout

你可能感兴趣的:(js)