javascript事件循环与宏任务 /执行栈/ 微任务

https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7

本文是对上述链接内容学习后的个人总结

 

任务队列

js中存在同步执行任务以及异步执行任务,主线程上的同步任务构成执行栈,异步任务会形成任务队列,当主线任务完成之后,会到任务队列中获取事件加入执行栈继续执行(遵循先进先出的原则)。

 

宏任务

(macro)task(又称之为宏任务),【浏览器】每执行完一个宏任务,再下一个宏任务开始之前会对页面进行重新渲染。

主要包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境);

 

微任务

microtask(又称为微任务),可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。当前宏任务结束之后下一个宏任务开始之前立即执行存在的所有微任务(先进先出)。

主要包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)

 

运行机制

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

 

setTimeout、Promise、Async/Await区别

在一个宏任务执行过程中如果遇到setTimeout(等宏任务源)会将这些宏任务源依次添加到宏任务列表中,等待下一次执行。

Promise中的异步体现在thencatch中,所以写在Promise中的代码是被当做同步任务立即执行的,其Promise.then内代码属于微任务源,遇到则依次添加到微任务列表中。

而在async/await中,在出现await出现之前,其中的代码也是立即执行的。出现await后await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码。

async function async1() {
	console.log('async1 start');
	await async2();
	console.log('async1 end');
}
黑斜体部分等价
async function async1() {
	console.log('async1 start');
	Promise.resolve(async2()).then(() => {
                console.log('async1 end');
        })
}

 

 

你可能感兴趣的:(javascript事件循环与宏任务 /执行栈/ 微任务)