# ❓setTimeout、Promise、Async/Await 的区别?

看题,这应该是考察 javascript 宏任务队列/微任务队列以及事件循环机制的问题。

我是这么理解的:

  • setTimeout 本身是一个宏任务

    // 代码的执行顺序,就跟打印的号码顺序一样
    // 一次只能执行一个宏任务
    // 遇到setTimeout 宏任务 推入宏任务队列
    // 继续执行 执行完毕发现没有微任务 执行下一个宏任务
    // 以此类推 这也是 js 事件循环机制
    console.log(1);
    setTimeout(() => {
      console.log("setTimeout 3");
    });
    console.log(2);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • Promise 自身是宏任务 但回调是微任务

    // 也是一道经典的面试题目
    
    // 也是一样 执行顺序就是打印的号码
    // 第一次宏任务开始执行
    console.log(1);
    new Promise((resolve, reject) => {
      console.log(2);
      resolve();
      console.log(3);
    }).then(() => {
      // 第一次宏任务 附带的微任务
      // 所以要在第一次宏任务走完的时候要执行掉
      console.log(5);
    });
    // 第二次宏任务注册
    // 推入宏任务队列
    setTimeout(() => {
      console.log(6);
    });
    console.log(4);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • Async/Await 关键字:async await 本质上还是基于 promise 的一些封装

    // 被添加入下一次宏任务队列
    setTimeout(_ => console.log(6));
    
    async function test() {
      console.log(1);
      // 我的理解是
      // 遇到 await 先执行其同步内容
      // 让出执行线程(跳出当前任务)同时推入微任务队列  继续往下执行
      // 执行完之后 回来继续执行
      await new Promise((resolve, reject) => {
        console.log(2);
        resolve();
      }).then(_ => console.log(4));
      // 这里 5 没有进入微任务队列 只不是相当于被挂起了
      console.log(5);
    }
    
    test();
    test();
    
    console.log(3);
    // 如果执行一次 test 函数  结果 => 123456
    // 如果执行两次 test 函数  结果 => 1212344556
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

# 宏任务有哪些呢?

# 浏览器 node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

# 微任务有哪些呢?

# 浏览器 node
process.nextTick
MutationObserver
Promise.then catch finally