宏任务、微任务、同步任务、异步任务理解

101 阅读2分钟

宏任务、微任务、同步任务、异步任务的执行顺序

关于这四个的执行顺序,今天梳理了一遍,用白话记录一下

先区分同步任务和异步任务:

同步任务:立即执行的任务,直接被JS主线程读取并执行

异步任务:异步执行的任务,会交给任务队列,在宿主环境中执行(宿主环境一般包括:浏览器、node环境)

为什么分为同步任务和异步任务?因为JS是单线程的,如果不区分同步和异步任务,那遇到耗时任务的时候,进程就会卡在当前无法往下走,所以又将非耗时任务归为同步任务,耗时任务归位异步任务。其中异步任务又分为微任务和宏任务。

● 常见的微任务包括: promise 的回调

● 常见的宏任务包括: script 脚本的执行、setTimeout ,setInterval 可以理解为耗时长的任务

关于四个的执行顺序见如下代码

setTimeout(() => {
  console.log(1);
  new Promise((resolve, rej) => {
    console.log(6);
    resolve(7);
  })
    .then((res) => {
      console.log(res);
      return new Promise((resolve, rej) => {
        resolve(9999);
      });
    })
    .then((res) => {
      console.log(res);
    });
  console.log(8);
}, 200);

setTimeout(() => {
  console.log(9);
  new Promise((resolve, rej) => {
    console.log(10);
    resolve(11);
  }).then((res) => {
    console.log(res);
  });
  console.log(12);
}, 300);

console.log(2);

new Promise((resolve, reject) => {
  console.log(3);
  resolve(4);
})
  .then((res) => {
    console.log(res);
    return new Promise((resolve, rej) => {
      resolve(5);
    });
  })
  .then((res) => {
    console.log(res);
  });

一、看所有同步任务,两个setTimeout显然不会立即执行,肉眼可见的是(2),new Promise的过程是同步的,但.then里面的代码上述说了promise回调是异步的,所以 (2、3)

二、同步任务执行完后,执行异步代码,异步中(一个promise回调,两个setTimeout)先执行微任务 (promise),promise回调中执行顺序(4、5),所以输出(2,3,4,5)

三、所有微任务队列执行完后,执行一个宏任务(第一个setTimeout时间短,先执行),执行过程中,发现promise,放到微任务队列,此时输出(1,6,8),然后执行下一个宏任务,setTimeout。!!注意 执行下一个宏任务之前,会检查微任务队列有没有任务,如果有,执行所有队列中的微任务。此时输出(7、9999),所以控制台目前(2,3,4,5,1,6,8,7,9999)。执行完所有任务队列中的微任务后,执行下一个宏任务(setTimeout)结果同理(9,10,12)后,放promise到微任务队列,然后输出(11)

最终结果(2,3,4,5,1,6,8,7,9999,9,10,12,11)