事件循环机制

396 阅读2分钟

1. 你了解浏览器中的事件循环机制(Event Loop)吗?

1.1 为什么js在浏览器中有事件循环机制?

​ js是单线程语言,为了解决各类浏览器事件同时触发时,如何排队依次执行,就需要事件循环机制。

1.2 事件循环中的两种任务:

	- 宏任务(Task Queue):js代码执行,`setTimeout``setInterval`, I/O操作
	- 微任务(Microtask Queue):`new Promise().then`, `MutaionObserver`

1.3 为什么要引入微任务的概念,只有宏任务可以吗?

​ 调整浏览器事件的优先级,可以让紧急任务快速响应,提高用户使用体验。

1.4 浏览器中的事件循环过程:

  1. 从宏任务队列中取出一个可执行任务,如果有则执行,没有下一步。
  2. 挨个取出微任务队列中的所有任务执行,执行完毕或没有则下一步。
  3. 浏览器渲染。

1.5 Node中的事件循环和浏览器中的有什么区别?

  • Node中的宏任务执行顺序:

    1. timers定时器:执行已经安排的setTimeoutsetInterval的回调函数
    2. pending callback 待定回调:执行延迟到下一个循环迭代的I/O回调
    3. idle,prepare:仅系统内部使用
    4. poll:检索新的I/O事件,执行与I/O相关的回调
    5. close callbacks
  • Node中的事件循环:

    • Node v10及以前:
      1. 执行完一个阶段中的所有任务
      2. 执行nextTick队列里的内容
      3. 执行完微任务队列的内容
    • Node v10以后:和浏览器的事件循环机制一样

1.6 看代码写输出:

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');

运行结果:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

1.7 看代码写输出:

console.log('start');
setTimeout(() => {
  console.log('children2');
  Promise.resolve().then(() => {
    console.log('children3');
  })
}, 0);

new Promise(function (resolve, reject) {
  console.log('children4');
  setTimeout(function () {
    console.log('children5');
    resolve('children6');
  }, 0);
}).then((res) => {
  console.log('children7');
  setTimeout(() => {
    console.log(res);
  }, 0);
});

运行结果:

start
children4
children2
children3
children5
children7
children6

1.8 看代码写输出:

const p = function () {
  return new Promise((resolve, reject) => {
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1);
      }, 0);
      resolve(2);
    });
    p1.then((res) => {
      console.log(res);
    });
    console.log(3);
    resolve(4);
  })
};

p().then((res) => {
  console.log(res);
});
console.log('end');

运行结果:

3
end
2
4