JS运行机制:事件循环,宏任务与微任务

JS运行机制

事件循环

定义:JavaScrript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。

首先来看一下这个模型:

事件循环模型1.png

:函数调用形成了一个由若干帧组成的栈;

:对象被分配在堆中,用来表示一大块内存区域的计算机术语;

队列:一个JavaScript运行的时候包含了一个待处理消息的队列,而每一个消息都关联着一个用于处理这个消息的回调函数;(消息队列也叫任务队列)

事件循环:之所以称之为 事件循环,是因为它经常按照类似如下的方式来被实现:

while (queue.waitForMessage()) {
  queue.processNextMessage();
}
复制代码

再结合以下代码进行分析:

function foo(b) {
  let a = 10;
  return a + b + 11;
}

function bar(x) {
  let y = 3;
  return foo(x * y);
}

console.log(bar(7)); // 返回 42
复制代码

在事件循环期间的某个时刻,运行时会从最新进入队列的消息开始处理。被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数。

对以上这段代码的执行顺序进行分析:

  1. 当调用console.log(bar(7))时,产生一个消息,进入消息队列;
  2. 当调用bar的时候,第一个帧被创建并压入栈中,帧中包含了bar的参数和局部变量;
  3. bar调用foo时,第二个帧被创建并被压入栈中,放在第一个帧上,帧中包含了foo的参数和局部变量;
  4. foo执行完毕后返回时,第二个帧出栈,当bar执行完毕返回后,第一个帧出栈,此时栈被清空;
  5. 所有执行栈清空后,这个消息执行结束,事件循环将会处理消息队列中的下一个消息(如果还有的话);

tips:在上面这段代码中,整个过程中只产生了一个任务。

宏任务与微任务

宏任务:

定义:每次执行栈执行的代码就是一个宏任务,宏任务是浏览器规定的;

可以生成宏任务的场景:setTimeout、setInterval、Ajax、DOM 事件

微任务

定义:在当前宏任务结束后立即执行的任务,微任务是由JS语法规定的;

可以生成微任务的场景:Promise async/await

执行顺序

宏任务和微任务的执行顺序:

  1. 执行一个宏任务;
  2. 如果执行宏任务的过程中遇到了微任务,将微任务添加到微任务队列中;
  3. 当前宏任务执行完毕后,立即去执行微任务队里中的微任务;
  4. 微任务执行完毕后,如果有宏任务的话再去执行下一个宏任务;

所以说:微任务早于宏任务执行

示例

console.log('1')
new Promise((resolve, reject) => {
  resolve('2')
}).then((res) => {
  console.log(res)
})
setTimeout(() => {
  console.log('3')
})
new Promise((resolve, reject) => {
  resolve('4')
}).then((res) => {
  console.log(res)
})
console.log('5')
复制代码

以上代码的执行结果为1,5,2,4,3

参考文档

MDN-并发模型与事件循环

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享