JS的执行机制(EventLoop、宏任务和微任务)

yizhihongxing

JavaScript是一门单线程语言,即一次只能处理一件事情。但是,JavaScript中有很多异步处理机制。了解JavaScript中的执行机制(Event Loop、宏任务和微任务),对于理解异步处理机制,以及优化代码执行效率非常重要。

Event Loop

Event Loop是JavaScript中执行的机制,它是一个循环处理异步任务的过程。它会检查是否有需要执行的任务,以及这些任务是宏任务还是微任务,来安排何时执行它们。

每个Event Loop都有一个消息队列,用于存储待执行的宏任务和微任务。当事件被添加到队列时,Event Loop总是按照以下顺序处理队列中的任务:

  • 执行当前宏任务中的同步任务;
  • 执行微任务队列中的任务,直到队列为空;
  • 取出下一个宏任务并执行;
  • 回到2。

宏任务和微任务

宏任务是一些较大的任务,如setTimeout、setInterval、ajax等等。它们被添加到宏任务队列中,等待Event Loop处理。宏任务总是会在微任务之前执行。

微任务是一些较小的任务,如Promise的then和catch方法,MutationObserver等等。它们被添加到微任务队列中,等待Event Loop处理。微任务总是会在下一个宏任务之前执行。

由于宏任务的执行需要一定的时间,因此在一个宏任务中可能会产生多个微任务。当一个宏任务执行结束时,Event Loop会检查微任务队列,将队列中的所有任务依次执行,直到队列为空。然后Event Loop再从宏任务队列中取出下一个任务并执行。

示例

示例1

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

上述代码的执行过程如下:

  1. 执行console.log('script start'),输出 "script start"。
  2. 执行setTimeout(...)会将其添加到宏任务队列,等待下一次Event Loop执行时执行。
  3. 执行Promise.resolve(),会将其添加到微任务队列。
  4. 执行console.log('script end'),输出 "script end"。
  5. 当前宏任务执行结束,Event Loop会检查微任务队列,将其队列中的任务依次执行,即输出 "promise1" 和 "promise2"。
  6. 微任务队列为空,Event Loop将取出下一个宏任务,即执行setTimeout中的回调函数,输出 "setTimeout"。

最终输出结果为:

script start
script end
promise1
promise2
setTimeout

示例2

console.log('script start');

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

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

console.log('script end');

上述代码中,添加了一个额外的Promise任务。Promise.resolve()创建了一个新的微任务,它包含了另一个Promise.resolve(),这个Promise.resolve()又创建了一个新的微任务,即:Promise.resolve().then(...)

上述代码的执行过程如下:

  1. 执行console.log('script start'),输出 "script start"。
  2. 执行setTimeout(...),添加它到宏任务队列中,等待下一次Event Loop执行。
  3. 执行Promise.resolve(),添加它到微任务队列中。
  4. 执行console.log('script end'),输出 "script end"。
  5. 当前宏任务执行结束,Event Loop会检查微任务队列,发现queue中有一个微任务,输出 "promise1"。
  6. 执行queue中微任务的Promise.resolve(),在微任务队列中添加一个新的微任务。
  7. Event Loop检查微任务队列,发现微任务队列中有一个任务,执行它,输出 "promise2"。
  8. 微任务队列为空,Event Loop继续处理宏任务队列,执行setTimeout中的回调函数,输出 "setTimeout"。

最终输出结果为:

script start
script end
promise1
promise2
setTimeout

通过以上两个示例,我们可以更清晰地了解JavaScript的执行机制,Event Loop、宏任务和微任务的关系,对于理解JavaScript异步处理机制和代码效率优化非常有帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS的执行机制(EventLoop、宏任务和微任务) - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 用JObj实现的渐变效果

    下面我来详细讲解一下“用JObj实现的渐变效果”的完整攻略。 什么是JObj JObj是JavaFX中提供的一个渐变类,可以让开发者方便地实现渐变效果。它是一个抽象类,有两个具体的实现类:LinearGradient 和 RadialGradient。 JObj中的五个属性 任何一个 JObj 都具备五个属性: CycleMethod(循环方式) Stop(…

    JavaScript 2023年6月10日
    00
  • 使用JS实现一个Sleep函数的示例代码

    使用 JS 实现一个 sleep 函数的示例代码攻略如下: 1. Sleep 函数是什么? Sleep 函数是一个常用的时间延迟函数,可以阻塞程序在一定时间内执行,使得程序停止一段时间再执行后续代码,通常用于实现动画等场景。在 JavaScript 中,由于单线程的特性不能直接使用 sleep 函数,但是可以使用异步操作和定时器来实现类似的效果。 2. 使用…

    JavaScript 2023年6月11日
    00
  • JavaScript 跨域之POST实现方法

    下面是详细讲解“JavaScript 跨域之POST实现方法”的完整攻略。 什么是跨域? 跨域是指在同一页面中,页面中的资源通过不同的域名来访问。比如,你的页面在 A 域名,但是想要访问 B 域名上的资源,这就是跨域。 常见的跨域问题 Ajax 跨域请求 iframe 跨域嵌套 脚本跨域请求 解决方法 跨域问题的解决方法有很多,这里重点介绍两种解决 Ajax…

    JavaScript 2023年5月27日
    00
  • JavaScript数据类型的存储方法详解

    JavaScript数据类型的存储方法详解 1. JavaScript数据类型简介 在JavaScript中,共有以下七种数据类型: 原始类型:Number、String、Boolean、null、undefined、Symbol 引用类型:Object 2. 数据类型的存储方式 2.1 原始类型的存储方式 原始类型的数据直接存储在栈内存中,它们的值可以直接…

    JavaScript 2023年6月11日
    00
  • js实现获取两个日期之间所有日期的方法

    首先,我们可以利用 JavaScript 中的 Date 对象来进行日期计算和格式化,从而实现获取两个日期之间所有日期的方法。以下是实现方法的步骤: 定义一个函数,接收两个参数,表示开始日期(start)和结束日期(end)。 利用 Date.parse() 方法将日期字符串转换为时间戳,方便后面的计算。 利用 Math.abs() 方法求出两个日期之间的毫…

    JavaScript 2023年5月27日
    00
  • 再谈JavaScript线程

    再谈JavaScript线程 在 JavaScript 的多线程模型中,主线程(也称为 UI 线程)是唯一的线程,负责执行 JavaScript 代码、渲染页面,以及处理用户交互事件等任务。由于 JavaScript 是单线程执行的,因此它的处理能力是有限的。当某个耗时的任务需要执行时,主线程就会被阻塞,页面就会失去响应,用户体验也会受到影响。为了解决这个问…

    JavaScript 2023年5月28日
    00
  • js contains方法实现代码

    当我们需要在一个字符串中查找特定字符或子串时,可以使用JavaScript提供的 contains() 方法。下面是实现 contains() 方法的代码: String.prototype.contains = function(substr) { return this.indexOf(substr) !== -1; } 这里定义了一个全局方法 Stri…

    JavaScript 2023年5月28日
    00
  • 详细聊聊JS中不一样的深拷贝

    下面我将详细讲解JS中不一样的深拷贝的完整攻略。 什么是深拷贝 深拷贝是指将一个对象完整复制一份并生成一个新对象,新对象和旧对象互不影响,即使新对象被修改了,旧对象也不会发生改变。 JavaScript 中的深拷贝 在 JavaScript 中,拷贝对象的方法是 Object.assign() 或者使用扩展运算符 …。然而,这些拷贝方法都只能进行浅拷贝。…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部