【event loop】javaScript事件循环机制

223 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

什么是 event loop?

  • 虽然 js 是单线程的语言,但是在运行上存在同步任务异步任务,具体表现为执行顺序不相同,event loop 机制规定了 js 的执行顺序,使得 js 单线程运行时不会阻塞

  • Javascript 有一个主线程main thread和调用栈(执行栈)call-stack和任务队列task queue,所有的任务都会被放到调用栈等待主线程执行

  • 同步任务会在调用栈中按照入栈顺序待主线程执行,异步任务的回调会在满足条件后被放入任务队列,主线程清空调用栈后会再去执行队列中的异步任务的回调

  • 异步任务又分为宏任务微任务,而主线程从任务队列中取出一个宏任务并执行,执行完毕后会清空队列中的微任务,再开始继续执行下一个宏任务

  • 宏任务->执行结束->有可执行的微任务吗?(有则执行所有微任务)->开始新的宏任务

  • 记住两点:

    • 微任务在宏任务之前的执行,先执行 执行栈中的内容 执行后 清空微任务
    • 每次取一个宏任务 就去清空微任务,之后再去取宏任务

宏任务和微任务都有哪些?

  • 宏任务(MacroTask):script标签整体代码的执行、setTimeoutsetIntervalI/OrequestAnimationFrameUI RenderingsetImmediate(Node.js 环境)
  • 微任务(MicroTask):Promise.thenMutationObserverprocess.nextTick(Node.js环境)catch finally

加餐

console.log('script start');

setTimeout(function () {
  console.log('setTimeout');
}, 0);

Promise.resolve()
  .then(function () {
    console.log('promise1');
  })
  .then(function () {
    console.log('promise2');
  });

console.log('script end');
//script start, script end, promise1, promise2, setTimeout
setTimeout(function () {
  console.log('setTimeout1');
  Promise.resolve().then(() => {
    console.log('then1');
  });
}, 0);
Promise.resolve().then(() => {
  console.log('then2');
  Promise.resolve().then(() => {
    console.log('then3');
  });
  setTimeout(function () {
    console.log('setTimeout2');
  }, 0);
});
//then2 then3 setTimeout1 then1 setTimeout2
let a = () => {
  setTimeout(() => {
    console.log('任务队列函数1');
  }, 0);
  for (let i = 0; i < 1; i++) {
    console.log('a的for循环');
  }
  console.log('a事件执行完');
};
let b = () => {
  setTimeout(() => {
    console.log('任务队列函数2');
  }, 0);
  for (let i = 0; i < 1; i++) {
    console.log('b的for循环');
  }
  console.log('b事件执行完');
};
let c = () => {
  setTimeout(() => {
    console.log('任务队列函数3');
  }, 0);
  for (let i = 0; i < 1; i++) {
    console.log('c的for循环');
  }
  console.log('c事件执行完');
};
a();
b();
c();
//a的for循环->a事件执行完->b的for循环->b事件执行完->c的for循环->c事件执行完->任务队列函数1->任务队列函数2->任务队列函数3
// 当a、b、c函数都执行完成之后,三个setTimeout才会依次执行