JavaScript之事件循环案例讲解

当用户在网页上操作时,我们需要通过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+html+css实现简单日历效果

    下面是 “js+html+css实现简单日历效果”的攻略: 1. 导入CSS和JS文件 在head标签中导入显示日历所需的CSS和JS文件 <head> <link rel="stylesheet" type="text/css" href="calendarStyle.css"&…

    JavaScript 2023年6月10日
    00
  • JavaScript中扩展Array contains方法实例

    下面是完整的攻略及示例。 扩展JavaScript中Array contains方法 在JavaScript中,Array原型对象已经提供了很多有用的方法,如push()、pop()、shift()、unshift()等。但是,有些时候我们可能需要自定义一些方法来满足特定的需求,而扩展contains()方法就是其中一个例子。 JavaScript中的Arr…

    JavaScript 2023年5月27日
    00
  • 使用JS判断页面是首次被加载还是刷新

    使用JS判断页面是首次被加载还是刷新,可以使用sessionStorage来进行判断,具体方法如下: 监听load事件,在事件处理函数中,判断sessionStorage是否存在对应的键值对。如果存在,说明页面是刷新后再次加载,反之则是首次加载。 示例代码: window.addEventListener(‘load’, function() { var i…

    JavaScript 2023年6月11日
    00
  • js substr支持中文截取函数代码(中文是双字节)

    下面是详细讲解“js substr支持中文截取函数代码(中文是双字节)”的完整攻略。 1. 问题背景 在JavaScript中,使用substr()方法可以截取指定位置和长度的字符串,但是它对中文不友好,因为中文字符是双字节的,在使用substr()方法截取时很容易出现截取不完整或截取错位的问题。因此,我们需要编写一个支持中文截取的函数。 2. 解决方案 我…

    JavaScript 2023年5月19日
    00
  • js中遍历对象的属性和值的方法

    在javascript中,有以下几种方法可以用于遍历对象的属性和值: 1. for…in 循环 for…in循环可以用于遍历对象的属性,但是它会遍历整个原型链上的可枚举属性,因此可能会获取到一些不需要的属性和方法。需要注意的是,对象的属性顺序是不保证的。 下面是一个使用for…in循环遍历对象的示例代码: const obj = {a: 1, b…

    JavaScript 2023年5月27日
    00
  • javascript结合Cookies实现浏览记录历史第1/3页

    对于“javascript结合Cookies实现浏览记录历史第1/3页”的完整攻略,以下为具体步骤: 1. 添加Cookie操作函数 在JavaScript中,需要先定义一些操作Cookie的函数。下面是一个可以添加、获取和删除Cookie的示例代码: // 添加Cookie function setCookie(name, value, expires) …

    JavaScript 2023年6月11日
    00
  • 浅谈JavaScript作用域

    当我们了解JavaScript时,作用域是一个十分重要的概念。它是指 JavaScript 中变量的可访问性。本文将浅谈 JavaScript 的作用域及其相关概念,并通过两个例子来说明作用域的不同。 全局作用域 在 JavaScript 中,最顶层的作用域被称为全局作用域。全局作用域中的变量和函数在代码的任何地方都是可访问的。可以通过以下代码来定义一个全局…

    JavaScript 2023年5月27日
    00
  • 使用JavaScript 定义自己的ajax函数

    使用JavaScript 定义自己的ajax函数,可以避免使用第三方库,能够更好地对代码进行掌控,实现更精细化的交互效果。 以下是使用JavaScript 定义自己的ajax函数的完整攻略及示例说明: 定义ajax函数 我们可以使用 JavaScript 进行定义 ajax 函数,以便方便在后续的代码中使用。下面展示一个基本的 ajax 函数定义示例: fu…

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