event loop

执行顺序

  • 首先执行 script 宏任务
  • 执行同步任务,遇见宏任务放入宏任务队列,微任务放入微任务队列
  • 当前宏任务执行完毕出队列,执行微任务,直至微任务执行完毕
  • 执行浏览器 UI 线程渲染
  • 执行 web worker
  • 执行下一个宏任务,回到第二步,依次循环,直至宏任务和微任务队列清空

宏任务:script、setTimeout、setInterval、UI rendering、new Promise
微任务:promise.then、promise.catch

例 1

const promise = new Promise((resolve)=>{
  console.log(1);
  resolve();
});

setTimeout(()=>{
  console.log(2);
});

promise.then(()=>{
  console.log(3);
})

console.log(4);

// 1 4 3 2

  • 首先 promise 构造函数同步执行,输出 1
  • 再 resolve 修改 promise 状态 pending 为 resolved,将 resolve 值保存,此处未传值
  • 跳出 promise,遇见 setTimeout 宏任务,放入宏任务队列
  • 接着遇见 promise.then 这个微任务,放入微任务队列
  • 执行同步代码,输出 4
  • 接着检查微任务队列是否执行完毕,输出 3
  • 微任务队列执行完毕,执行宏任务,输出 2

例 2

const promise = new Promise((resolve,reject)=>{
  console.log(1);
  resolve();
  reject();
});

promise.then(()=>{
  console.log(2);
})

promise.catch(()=>{
  console.log(3);
})

console.log(4);

// 1 4 2
  • 首先 promise 构造函数同步执行,输出 1
  • 再 resolve 修改 promise 状态 pending 为 resolved,将 resolve 值保存,此处未传值
  • 再 reject ,promise 的状态已经修改为 resolved,不能再次修改(promise 状态值只能由 pending 变为 resolved 或者 pending 变为 rejected,不能再次翻转状态)
  • 跳出 promise,遇见 promise.then 方法,放入微任务队列
  • 接着遇见 promise.catch 方法,不执行
  • 执行同步代码,输出 4
  • 检查微任务队列是否执行完毕,执行 then 方法,输出 2

例 3

const promise = new Promise((resolve)=>{
  console.log(1);
  setTimeout(()=>{
    console.log(2);
    resolve();
  },500);
});

promise.then(() => {
  console.log(3)
})

console.log(4);

// 1 4 2 3

  • 首先 promise 构造函数同步执行,输出 1
  • 遇见宏任务 setTimeout,放入宏任务队列中
  • 遇见 promise.then ,因为此时 promise 的状态还在 pedding,不明确是 resolved,还是 rejected,所以放入 promise 回调数组
  • 执行同步代码,输出 4
  • 检查微任务队列为空
  • 执行宏任务队列 setTimeOut,输出 2,修改 promise 状态为 resolved ,放入微任务队列,setTimeOut 宏任务出队
  • 检查微任务队列,执行 promise.then 方法,输出 3

例 4

const promise = new Promise((resolve)=>{
  console.log(1);
  setTimeout(()=>{
    console.log(2);
    resolve();
  },500);
});

promise.then(
  console.log(3)
)

console.log(4);

// 1 3 4 2

  • 首先 promise 构造函数同步执行,输出 1
  • 遇见宏任务 setTimeout,放入宏任务队列中
  • 遇见 promise.then ,promise.then 或者promise.catch 方法期待接收函数作为参数,传入非函数会发生值透传,此时传入的为非函数,立即执行,输出 3
  • 执行同步代码,输出 4
  • 检查微任务队列为空
  • 执行宏任务队列 setTimeOut,输出 2,修改 promise 状态为 resolved ,setTimeOut 宏任务出队

总结

  • 首先执行同步代码,遇见微任务放入微任务队列,宏任务放入宏任务队列
  • 先清空微任务队列,再执行宏任务
  • promise 的构造函数是同步执行,promise.then 或者 promise.catch 方法异步执行
  • promise 的状态一直 pendding,需要放入 promise 的回调函数,等状态修改后,再把 promise.then 或者 promise.catch 方法放入微任务
  • promise 状态值只能由 pending 变为 resolved 或者 pending 变为 rejected,不能再次翻转状态
    -promise.then 或者promise.catch 方法期待接收函数作为参数,传入非函数会发生值透传

版权声明:本文为Alexling0原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。