Promise & Event Loop Demo Collections

92 阅读5分钟

Event Loop是在宏任务和微任务之间交替执行的, 即每执行完一个宏任务紧接着就会去执行微任务, 执行完微任务后再执行下一个宏任务, 以此循环下去.

在执行宏任务的过程中, 同步代码直接执行, 异步代码要么进入宏任务队列要么进入微任务队列.

  • []表示微任务队列
  • [[]]表示宏任务队列
  • [xxx] 表示 console.log('xxx') 所在的函数入队微任务队列

demo 1.0

Promise.resolve()
  .then(() => {
    console.log("then1");
    Promise.resolve().then(() => {
      console.log("then1-1");
    });
  })
  .then(() => {
    console.log("then2");
  });
// 过程解析:
// 执行 Promise.resolve , promise 状态已确定, 故入队微任务并执行微任务
// [then1] 
// log -> then1
// 内部 promise 状态已确定, 入队微任务[then1-1]
// 至此, 第一个 then 执行完, 所以其返回的 promise 状态也就确定, 因此将 then2 入队微任务队列
// [then1-1,then2]
// log -> then1-1 -> then2

demo2.0

let p = Promise.resolve().then(() => {
  console.log("then1");
  Promise.resolve().then(() => {
    console.log("then1-1");
  });
}).then(() => {
  console.log("then2");
});

p.then(() => {
  console.log("then3");
});
// 解析过程:
// 首先入队微任务 [then1] 并执行
// log -> then1
// 入队[then1-1]
// then2 / then3 同属一个 promise
// 依次入队[then1-1,then2,then3]
// log -> then1-1 -> then2 -> then3

demo3.0

Promise.resolve()
  .then(() => {
    console.log("then1");
    Promise.resolve()
      .then(() => {
        console.log("then1-1");
        return 1;
      })
      .then(() => {
        console.log("then1-2");
      });
  })
  .then(() => {
    console.log("then2");
  })
  .then(() => {
    console.log("then3");
  })
  .then(() => {
    console.log("then4");
  });
// 解析过程:
// 入队[then1]并执行
// log -> then1
// 入队[then1-1]
// 第一个 then 到此执行完毕, 入队 then2
// 入队[then1-1,then2]
// log -> then1-1
// [then2,then1-2]
// log -> then2
// [then1-2,then3]
// log -> then1-2
// log -> then3
// [then4]
// log -> then4
// result: then1 - then1-1 - then2 - then1-2 - then3 - then4

demo4.0 (3.0改版)

Promise.resolve()
  .then(() => {
    console.log("then1");
    Promise.resolve()
      .then(() => {
        console.log("then1-1");
        return Promise.resolve();
      })
      .then(() => {
        console.log("then1-2");
      });
  })
  .then(() => {
    console.log("then2");
  })
  .then(() => {
    console.log("then3");
  })
  .then(() => {
    console.log("then4");
  });
// 解析过程: return Promise.resolve 会多触发两次微任务, 以 undefined 代表
// log -> then1
// [then1-1,then2]
// log -> then1-1
// [then2,undefined]
// log -> then2
// [undefined,then3]
// [then3,undefined]
// log -> then3
// [undefined,then4]
// [then4,then1-2]
// log -> then4 
// log -> then 1-2

demo5.0

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    return new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
    .then(() => {
        console.log("内部第一个then");
    })
    .then(() => {
        console.log("内部第二个then");
    });
  })
  .then(() => {
    console.log("外部第二个then");
  });
// 过程解析:
// log -> 外部promise
// [外部第一个then]
// log -> 外部第一个then -> 内部promise
// [内部第一个then]
// log -> 内部第一个then
// [内部第二个then]
// log -> 内部第二个then
// return 后的 promise 完成, 即第一个 then 执行完
// [外部第二个then]
// log -> 外部第二个then

demo6.0 (5.0改版)

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
      .then(() => {
        console.log("内部第一个then");
      })
      .then(() => {
        console.log("内部第二个then");
      });
  })
  .then(() => {
    console.log("外部第二个then");
  });
// 解析过程:
// log -> 外部promise
// [外部第一个then]
// log -> 外部第一个then
// log -> 内部 promise
// [内部第一个then]
// [内部第一个then, 外部第二个then]
// log -> 内部第一个then
// [外部第二个then, 内部第二个then]
// log -> 外部第二个then -> 内部第二个then

demo7.0

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    let p = new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
    p.then(() => {
        console.log("内部第一个then");
      })
    p.then(() => {
        console.log("内部第二个then");
      });
  })
  .then(() => {
    console.log("外部第二个then");
  });
// 解析过程:
// log -> 外部 promise
// [外部第一个 then]
// log -> 外部第一个 then -> 内部 promise
// [内部第一个 then, 内部第二个 then]
// log -> 内部第一个 then -> 内部第二个 then
// [外部第二个 then]
// log -> 外部第二个 then

demo8.0

let p = new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
p.then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
      .then(() => {
        console.log("内部第一个then");
      })
      .then(() => {
        console.log("内部第二个then");
      });
  })
p.then(() => {
    console.log("外部第二个then");
  });
// 解析过程:
// log -> 外部 promise
// [外部第一个then,外部第二个then] , 同属一个 promise 对象 p
// log -> 外部第一个then
// log -> 内部 promise
// [外部第二个then, 内部第一个then]
// log -> 外部第二个then
// [内部第一个then]
// log -> 内部第一个then
// [内部第二个 then]
// log -> 内部第二个then

demo9.0

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
      .then(() => {
        console.log("内部第一个then");
      })
      .then(() => {
        console.log("内部第二个then");
      });
    // return 意味着 外部第二个then 必须等待这个 new Promise() 执行完
    return new Promise((resolve, reject) => {
      console.log("内部promise2");
      resolve();
    })
      .then(() => {
        console.log("内部第一个then2");
      })
      .then(() => {
        console.log("内部第二个then2");
      });
  })
  .then(() => {
    console.log("外部第二个then");
  });
// 解析过程:
// log -> 外部 promise
// [外部第一个 then]
// log -> 外部第一个 then -> 内部 promise
// [内部第一个then]
// log -> 内部promise2
// [内部第一个then, 内部第一个then2]
// log -> 内部第一个then
// [内部第一个then2, 内部第二个then]
// log -> 内部第一个then2
// [内部第二个then, 内部第二个 then2]
// log -> 内部第二个 then
// [内部第二个then 2]
// log -> 内部第二个then2
// 至此第一个 then 的 return new Promise() 执行完
// [外部第二个then]
// log -> 外部第二个then

demo10.0

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
.then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
        console.log("内部promise");
        resolve();
    })
    .then(() => {
        console.log("内部第一个then");
    })
    .then(() => {
        console.log("内部第二个then");
    });
    return new Promise((resolve, reject) => {
        console.log("内部promise2");
        resolve();
    })
    .then(() => {
        console.log("内部第一个then2");
    })
    .then(() => {
        console.log("内部第二个then2");
    });
})
.then(() => {
    console.log("外部第二个then");
});
// 解析过程:
// log -> 外部 promise
// [外部第一个 then]
// log -> 外部第一个 then
// log -> 内部 promise
// [内部第一个 then]
// log -> 内部 promise2
// [内部第一个 then, 内部第一个 then2]
// log -> 内部第一个 then
// [内部第一个 then2, 内部第二个 then]
// log -> 内部第一个 then2
// [内部第二个 then, 内部第二个 then2]
// log -> 内部第二个 then
// log -> 内部第二个 then2
// return new Promise()执行完
// [外部第二个 then]
// log -> 外部第二个 then

demo11.0

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');
// 解析过程:
// log -> script start
// [[setTimeout]]
// log -> async1 start
// log -> async2
// [async2]
// log -> promise1
// [async2, promise2]
// log -> script end
// 同步代码执行完成, 开始执行微任务队列
// log -> async1 end
// log -> promise2
// 再执行宏任务
// log -> setTimeout

参考文档

深度揭秘 Promise 微任务注册和执行过程

Promise 你真的用明白了么?