JavaScript之事件循环案例讲解

yizhihongxing

当用户在网页上操作时,我们需要通过JavaScript代码来响应用户的事件,例如点击、滚动、输入等等。但是由于JavaScript是单线程执行的,如果在响应事件的同时还要执行许多其他的代码,就会导致页面出现卡顿、响应迟缓的问题。为了解决这个问题,JavaScript引入了事件循环机制。

什么是事件循环

事件循环是JavaScript引擎实现多任务的基础,在执行JavaScript代码时,主线程会不断地从任务队列中取出任务并执行。如果任务队列中没有任务,主线程就会等待任务出现。

任务队列分为两种类型:宏任务(macro-task)和微任务(micro-task)。宏任务包括DOM事件、定时器任务、网络请求等,而微任务主要有Promise、MutationObserver等。

当主线程执行完一个宏任务后,会立即去检查是否有微任务需要执行,如果有,则依次取出并执行这些微任务,直到所有微任务都被执行完毕,才会再次取出下一个宏任务执行。

事件循环的示例

示例一

假设我们有如下代码:

console.log('Task1');

setTimeout(() => {
  console.log('Task2');
}, 0);

Promise.resolve().then(() => {
  console.log('Task3');
});

console.log('Task4');

按照事件循环的执行顺序,程序会先执行主线程中的当前任务(即Task1),然后检查微任务队列,发现有一个Promise的回调函数(即Task3),于是执行Promise的回调函数。接着,再次检查有没有微任务,此时微任务队列为空。

由于我们设置了一个0ms的定时器(即Task2),因此Task2会被加入宏任务队列,此时主线程中没有其他任务,于是会去执行Task2。执行完Task2后,又会检查微任务队列,发现队列中为空,于是继续检查宏任务队列。

最后,剩下的一条任务是Task4,于是会被主线程执行。整个程序的输出结果如下:

Task1
Task4
Task3
Task2

可以看到,虽然定时器设置的是0ms,但是定时器回调函数Task2并没有立即执行,而是在所有微任务都被执行完毕后才被执行。

示例二

再看一个复杂一点的例子:

console.log('Task1');

setTimeout(() => {
  console.log('Task2');
}, 0);

Promise.resolve().then(() => {
  console.log('Task3');
  Promise.resolve().then(() => {
    console.log('Task4');
  });
}).then(() => {
  console.log('Task5');
});

console.log('Task6');

这个例子中,我们多了一层Promise,并在Promise的回调函数中嵌套了一个Promise的回调函数。

主线程首先执行Task1,然后将两个Promise的回调函数(Task3和Task4)放入微任务队列中。接着检查宏任务队列,发现有一个定时器,将Task2放入宏任务队列中。

执行完毕后,按照事件循环的顺序依次执行微任务队列中的Task3和Task4。注意,Task4是Task3的嵌套回调函数,因此在Task3执行完毕后才能执行Task4。

执行完毕微任务队列后,检查微任务队列,发现还有一个Task5,于是立刻执行该任务。

最后,主线程执行Task6。整个程序的输出结果如下:

Task1
Task6
Task3
Task4
Task5
Task2

总结

通过这两个例子,我们可以看到JavaScript引擎通过任务队列和事件循环机制实现了多任务的执行。在编写JavaScript代码的时候,我们需要注意事件循环的规则,合理地使用微任务和宏任务,避免出现卡顿、响应迟缓的情况。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript之事件循环案例讲解 - Python技术站

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

相关文章

  • 用js实现输入提示(自动完成)的实例代码

    想要实现输入提示(autocomplete)功能,我们通常需要以下几个步骤: 1. 获取用户输入 在实现自动完成功能之前,我们首先需要获取用户的输入。在网页中,我们可以通过<input>标签来实现用户输入信息的获取,例如: <label for="username">用户名:</label> <i…

    JavaScript 2023年6月10日
    00
  • JS中对象与字符串的互相转换详解

    下面是关于JS中对象与字符串的互相转换详解: 对象转字符串 在JS中,对象转成字符串通常使用JSON.stringify()函数,该函数将JavaScript对象转换为字符串,序列化过程中字符串中的对象、数组等会自动转成字符串。 以下是转换过程及示例代码: 基础用法 let obj = {name: ‘Mike’, age: 20, hobby: [‘rea…

    JavaScript 2023年5月27日
    00
  • 一些老手都不一定知道的JavaScript技巧

    一些老手都不一定知道的JavaScript技巧 1. 用单行代码实现一个简单的深拷贝 const deepCopy = obj => JSON.parse(JSON.stringify(obj)) 这个单行代码利用了JSON对于Object类型的序列化和反序列化功能,先将对象序列化为字符串,再将字符串反序列化为Javascript对象。这种方式可以实现…

    JavaScript 2023年5月18日
    00
  • js简单实现自动生成表格功能示例

    下面我详细讲解“js简单实现自动生成表格功能”的完整攻略。 思路分析 在实现自动生成表格的功能之前,我们需要考虑以下几个问题: 在什么情况下需要自动生成表格? 在很多情况下,我们需要将一些数据展示在网页上,同时这些数据可能十分庞大,用表格的形式展示更加直观且易于阅读。 自动生成表格需要哪些数据? 自动生成表格需要一个二维数组,表示表格中的每一个单元格的内容。…

    JavaScript 2023年5月28日
    00
  • Javascript Math tan() 方法

    JavaScript中的Math.SQRT2属性是一个常数,表示2的平方根。以下是关于Math.SQRT2属性的完整攻略,含两个示例。 JavaScript Math对象的SQRT2属性 JavaScript的SQRT2属性是一个常数,表示2的平方根。下面是SQRT2属性的语法: Math.SQRT2 下面是一个SQRT2属性的示例: console.log…

    JavaScript 2023年5月11日
    00
  • 详解ECMAScript6入门–Class对象

    以下是详解ECMAScript6入门–Class对象的完整攻略: ECMAScript6入门–Class对象 Class对象的概念 Class语法是ES6中一个新的语法,它提供了更加简洁、清晰的面向对象编程方式。Class本质上是一个语法糖,它的出现让原型继承的写法更加清晰易懂。 在ES6之前,继承只能通过原型链来进行实现,而这样的实现方式并不是很直观,…

    JavaScript 2023年5月27日
    00
  • jquery遍历json对象集合详解

    现在我来详细讲解一下“jQuery遍历JSON对象集合详解”的完整攻略。 1. 简介 在前端开发中,经常需要使用JSON数据格式来传输和存储数据。而jQuery是一个非常流行的JavaScript库,提供了丰富的API来处理JSON数据。本文将详细介绍如何使用jQuery遍历JSON对象集合,以及如何使用jQuery处理JSON数据。 2. 遍历JSON对象…

    JavaScript 2023年5月27日
    00
  • JS apply用法总结和使用场景实例分析

    JS apply用法总结和使用场景实例分析 apply()是JS中的一个函数方法,它可以改变函数的this值,并将一个数组作为函数的参数传递进去。本文将对apply()的作用、使用方式和常见应用场景进行详细讲解。 apply()的作用 apply()方法是定义在Function.prototype上的,它的作用是改变函数的this指向,并且可以将一个数组作为…

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