参考
微任务、宏任务与 Event-Loop
宏任务和微任务到底是什么?
JavaScript 中的 Event Loop(事件循环)机制
什么是 Event-Loop
JS 是单线程执行的,所以要执行多任务的话依赖于异步和事件循环(Event Loop)。JS 是单线程的,指的是 JS 引擎线程。在浏览器环境中,有 JS 引擎线程和渲染线程,且这两个线程互斥。node 环境中,只有 JS 引擎线程。
JS 引擎常驻内存,等待宿主(浏览器或 node)分配宏任务,反复等待-执行即为事件循环。

Event Loop 中,每次循环称为 tick,每次 tick 的任务如下:
- 读宏任务队列,执行其同步代码直至结束,这个过程中可能会有宏任务和微任务入队
- 读微任务,并执行,直至微任务队列为空
- 如果宿主为浏览器,可能会渲染页面
ES6 规范中,microtask 称为 jobs,macrotask 称为 task。宏任务是由宿主发起的,而微任务由 JavaScript 自身发起。
在 ES3 以及以前的版本中,JavaScript 引擎自身没有发起异步请求的能力,也就没有微任务的存在。在 ES5 之后,JavaScript 引入了 Promise,这样,不需要浏览器,JavaScript 引擎自身也能发起异步任务了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
function sync1(){ return new Promise((resolve, reject)=>{ console.log('async1 start'); return new Promise((resolve, reject) => { console.log('async2 start'); return new Promise((resolve, reject) => { console.log('async3 start'); resolve(); }).then(()=>{ console.log('async3 end'); resolve(); }) }).then(() => { console.log('async2 end'); resolve(); }) }).then(()=>{ console.log('async1 end'); }) }
console.log('script start');
setTimeout(function() { console.log('setTimeout'); }, 0);
sync1();
new Promise(function(resolve) { console.log('promise1 start'); resolve(); }).then(function() { console.log('promise1 end'); })
console.log('script end');
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| new Promise(resolve => { setTimeout(()=>{ console.log(1); new Promise(resolve => { resolve(); }) .then(() => {console.log(2);}) }) resolve(); }) .then(() => { console.log('then1') let a = new Promise(resolve => { resolve(); }) .then(() => {console.log(3);}) Promise.resolve().then(() => {console.log(4);}) .then(() => {console.log(5);}) .then(() => {console.log(6);}) console.log(7); }) .then(() => { console.log('then2') new Promise((resolve) => { resolve() }) .then(() => { console.log(8); new Promise((resolve) => { resolve() }) .then(() => {console.log(9)}) }) .then(() => { console.log(10); }) }) .then(() => { console.log('then3') console.log(11); }) .then(() => { console.log('then4') console.log(12); })
|
setTimeout回调函数是宏任务,Promise.then的回调函数是微任务
new Promise的 executor 函数是同步执行的
then需等new Promise的 executor 函数执行完,或上一个 then 执行完,才入队