JS基础 - 异步进阶 - 宏任务和微任务

前端开发·教程·资源 · 2022-06-26

1. 什么是宏任务和微任务

JavaScript 把异步任务又做了进一步的划分,异步任务又分为两类,分别是:

宏任务(macrotask): 宿主环境提供的异步方法都是宏任务

  • script全部代码
  • 异步 Ajax 请求
  • setTimeout、setInterval
  • 文件操作
  • DOM事件
  • I/O
  • UI
  • rendering

微任务(microtask):语言标准提供

  • Promise
  • Async / Await
  • mutationObserver
  • Process.nextTick(Node独有)

异步任务

2. Event Loop 和DOM渲染

console.log('script start');
setTimeout(() => {
    console.log('setTimeout');
}, 0);
new Promise((resolve) => {
    console.log('promise1');
    resolve();
});
const div = document.createElement('div')
div.innerHTML = '<h1>hello</h1>'
document.body.appendChild(div);
alert('我是一个alert');
console.log('script end');

// script start
// promise1
// 弹窗 我是一个alert DOM渲染
// script end
// setTimeout
由上面的执行结果可以看出DOM渲染是在微任务之后执行。DOM渲染后才会去执行宏任务;

3. 宏任务和微任务的根本区别

  • 微任务是由ECMAscript 2015(ES6)语法规定的,
  • 宏任务是由浏览器规定的。

4. 宏任务和微任务的执行顺序

异步任务执行顺序.png

  • 每一个宏任务执行完之后,都会检查是否存在待执行的微任务
  • 如果有,则执行完所有微任务之后,再继续执行下一个宏任务。
  • 当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

六、Event Loop执行顺序

Event Loop执行顺序

  1. JS是单线程的,按照顺序一行一行执行,如果某行报错则停止后续执行,然后就是「先执行同步,再执行异步」
  2. 看图,我们会将同步代码一行一行放入Call Stack中执行,
  3. 遇到异步代码就记录一下,在此过程中异步代码如果是宏任务移动到Web APIs,直到定时的时间到就放入任务队列,即图中的Callback Queue
  4. 如果是微任务则放入微任务队列,即图中的Mirco Task QueuePromiseES6规范的,不是W3C规范的所以不会经过Web APIs
  5. 如果同步代码执行完,调用栈Call Stack为空,去查看微任务队列,每执行完一个微任务,它就会从微任务队列出队,
  6. 直到微任务队列清空后,「这时候首先会尝试DOM渲染,之后再触发Event Loop机制」,(如果DOM结构发生变化)。
  7. 然后Event Loop开始工作,然后轮询查找Callback Queue,如有则移动到Call Stack执行...
  8. 每执行完一个宏任务,就会去检查微任务队列,若微任务队列有,就执行到微任务为空,再尝试DOM渲染,然后去看宏任务队列,继续轮询查找。

    ❝ 请注意:为什么是尝试DOM渲染,因为可能这一段JS代码里并没有修改DOM,尝试是代表着如果有对DOM的操作,那么去渲染,没有的话,忽略这一步。❞
ECMAScript Javascript笔记 Promise 异步 Event Loop 微任务 宏任务 DOM渲染 ES6 async/await
Theme Jasmine by Kent Liao