高级前端
js
【Q606】关于事件循环,仅有 Promise,判断以下代码输出

关于事件循环,仅有 Promise,判断以下代码输出

更多描述 代码见 Promise 事件循环代码输出顺序题目 - CodePen (opens in a new tab)

Promise.resolve(console.log(0))
  .then(() => {
    console.log(1);
    Promise.resolve(console.log(5))
      .then(() => console.log(3))
      .then(() => console.log(4))
      .then(() => console.log(6));
  })
  .then(() => console.log(2))
  .then(() => console.log(7));

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 624 (opens in a new tab)

Author 回答者: xiaoxiaohuayu (opens in a new tab)

按照我的理解应该是0,1,2,7,5,3,4,6

Author 回答者: shfshanyue (opens in a new tab)

0 1 5 3 2 4 7 6

以上代码可以看做以下代码的简写,此时思路就会清晰很多

Promise.resolve(console.log(0))
  .then(() => {
    console.log(1);
    const r = console.log(5);
    Promise.resolve(r)
      .then(() => {
        const r = console.log(3);
        return r;
      })
      .then(() => {
        const r = console.log(4);
        return r;
      })
      .then(() => {
        const r = console.log(6);
        return r;
      });
    return r;
  })
  .then(() => {
    const r = console.log(2);
    return r;
  })
  .then(() => {
    const r = console.log(7);
    return r;
  });

Author 回答者: xjxujing (opens in a new tab)

为了方便说明执行思路,把箭头函数换成了普通函数,起了名字,然后加上默认返回值 return undefined

Promise.resolve(console.log(0))
  .then(function F1() {
    console.log(1);
    Promise.resolve(console.log(5))
      .then(function F3() {
        console.log(3);
        return undefined;
      })
      .then(function F4() {
        console.log(4);
        return undefined;
      })
      .then(function F6() {
        console.log(6);
        return undefined;
      });
 
    return undefined;
  })
  .then(function F2() {
    console.log(2);
    return undefined;
  })
  .then(function F7() {
    console.log(7);
    return undefined;
  });

执行过程: 打印 0, F1 放入 microtask 调用栈空了, 从 microtask 拿 F1 执行 打印 1, 遇到 Promise.resolve 打印 5, 遇到 then, F3 放入 microtask 继续执行同步的代码 也就是 return undefined, 然后看到 then 然后把 F2 放入 microtask 调用栈空了, 从 microtask 按顺序拿 F3 执行 打印 3, 再遇到 return undefined, 然后看到 then, 再把 F4 放入 microtask 从 microtask 按顺序拿 F2 执行 打印 2, 再遇到 return undefined, 然后看到 then, 再把 F7 放入 microtask 从 microtask 按顺序拿 F4 执行 打印 4, 再遇到 return undefined, 然后看到 then, 再把 F6 放入 microtask 从 microtask 按顺序拿 F7 执行 打印 7 再遇到 return undefined, 没有 then 了 从 microtask 按顺序拿 F6 执行 打印 6

画个图大概是这样: image

Author 回答者: illumi520 (opens in a new tab)

多个promise then 的执行顺序是

  1. 按同步的运行顺序,执行 Promise 的构造函数

  2. 将所有 Promise 构造函数后的第一个 then() 函数放入异步队列中(如果存在的话)

  3. 将所有 Promise 构造函数后的第二个 then() 函数放入异步队列中(如果存在的话)

Author 回答者: liweinanone (opens in a new tab)

为了方便说明执行思路,把箭头函数换成了普通函数,起了名字,然后加上默认返回值 return undefined

Promise.resolve(console.log(0))
  .then(function F1() {
    console.log(1);
    Promise.resolve(console.log(5))
      .then(function F3() {
        console.log(3);
        return undefined;
      })
      .then(function F4() {
        console.log(4);
        return undefined;
      })
      .then(function F6() {
        console.log(6);
        return undefined;
      });
 
    return undefined;
  })
  .then(function F2() {
    console.log(2);
    return undefined;
  })
  .then(function F7() {
    console.log(7);
    return undefined;
  });

执行过程: 打印 0, F1 放入 microtask 调用栈空了, 从 microtask 拿 F1 执行 打印 1, 遇到 Promise.resolve 打印 5, 遇到 then, F3 放入 microtask 继续执行同步的代码 也就是 return undefined, 然后看到 then 然后把 F2 放入 microtask 调用栈空了, 从 microtask 按顺序拿 F3 执行 打印 3, 再遇到 return undefined, 然后看到 then, 再把 F4 放入 microtask 从 microtask 按顺序拿 F2 执行 打印 2, 再遇到 return undefined, 然后看到 then, 再把 F7 放入 microtask 从 microtask 按顺序拿 F4 执行 打印 4, 再遇到 return undefined, 然后看到 then, 再把 F6 放入 microtask 从 microtask 按顺序拿 F7 执行 打印 7 再遇到 return undefined, 没有 then 了 从 microtask 按顺序拿 F6 执行 打印 6

画个图大概是这样: image

very nice