# Event Loop

# 什么是 event loop?

  • 虽然 js 是单线程的语言,但是在运行上存在同步任务异步任务,具体表现为执行顺序不相同,event loop 机制规定了 js 的执行顺序,使得 js 单线程运行时不会阻塞
  • Javascript 有一个主线程main thread和调用栈(执行栈)call-stack和任务队列task queue,所有的任务都会被放到调用栈等待主线程执行
  • 同步任务会在调用栈中按照入栈顺序待主线程执行,异步任务的回调会在满足条件后被放入任务队列,主线程清空调用栈后会再去执行队列中的异步任务的回调
  • 异步任务又分为宏任务微任务,而主线程从任务队列中取出一个宏任务并执行,执行完毕后会清空队列中的微任务,再开始继续执行下一个宏任务
操作0=>operation: 宏任务
操作1=>operation: 执行结束
条件1=>condition: 有可执行的微任务吗?
操作2=>operation: 执行所有微任务

操作0->操作1->条件1(yes)->操作2->操作0
条件1(no)->操作1
  • 记住两点:
    • 微任务在宏任务之前的执行,先执行 执行栈中的内容 执行后 清空微任务
    • 每次取一个宏任务 就去清空微任务,之后再去取宏任务

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

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

# 加餐

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才会依次执行
Last Updated: 6/2/2022, 3:50:31 AM