关于 JavaScript 事件循环 Event Loop 的一些理解
浏览器 JavaScript 执行流程以及在 Node.js 中都是基于事件循环的。
了解事件循环的工作原理对于正确编写健壮和高性能的 JavaScript 代码非常重要。
本文首先介绍有关事物如何工作的理论细节,然后介绍这些知识的实际应用。
事件循环遵循下面的处理范式:
任务被设置——引擎处理它们——然后等待更多任务(在睡眠和消耗接近于零的 CPU 事件)。
如果在 JavaScript 执行引擎忙时又有新任务达到,这些新任务会被排队,形成一个队列,即所谓的 宏任务队列
(v8 术语)。
例如,当引擎忙于执行脚本时,用户可能会移动鼠标导致 mousemove,setTimeout 可能会到期等等,这些任务形成一个队列,如上图所示。
队列中的任务以 先到先处理
的方式被引擎处理。 当引擎浏览器完成脚本后,它会处理 mousemove 事件,然后是 setTimeout 处理程序,等等。
注意以下两点:
-
当引擎执行任务时,渲染永远不会发生。 任务是否需要很长时间并不重要。 仅在任务完成后才绘制对 DOM 的更改。
-
如果一项任务花费的时间太长,浏览器就无法执行其他任务,例如处理用户事件。 所以一段时间后,浏览器会发出
Page Unresponsive
之类的警报,建议用整个页面杀死任务。当有很多复杂的计算或导致无限循环的编程代码错误时,就会发生这种情况。
假设我们有一个 CPU 密集型任务。
例如,语法高亮(用于为本页上的代码示例着色)占用大量 CPU。为了突出显示代码,它执行分析,创建许多彩色元素,将它们添加到文档中。
当引擎忙于语法高亮时,它不能做其他与 DOM 相关的事情,处理用户事件等。它甚至可能导致浏览器失去响应。
我们可以通过将大任务分成几部分来避免问题。突出显示前 100 行,然后为接下来的 100 行安排 setTimeout(零延迟),依此类推。
为了演示这种方法,为了简单起见,让我们使用一个从 1 计数到 1000000000 的函数,而不是文本突出显示。
如果您运行下面的代码,JavaScript 引擎将 挂起
一段时间。如果在浏览器中运行,尝试单击页面上的其他按钮 - 会看到在计数完成之前没有其他事件得到处理。
let i = 0;
let start = Date.now();
function count() {
// do a heavy job
for (let j = 0; j < 1e9; j++) {
i++;
}
alert("Done in " + (Date.now() - start) + 'ms');
}
count();
将任务使用 setTimeout 拆分,确保队列中的其他任务有得到执行的机会:
let i = 0;
let start = Date.now();
function count() {
// do a piece of the heavy job (*)
do {
i++;
} while (i % 1e6 != 0);
if (i == 1e9) {
alert("Done in " + (Date.now() - start) + 'ms');
} else {
setTimeout(count); // schedule the new call (**)
}
}
count();
相关文章
- 【JavaScript】事件
- JavaScript中给onclick绑定事件后return false遇到的问题
- 总结JavaScript事件机制
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
- javascript中this指针探讨
- 第一百二十节,JavaScript事件对象
- Javascript事件绑定的几种方式
- [Poi] Use Poi to Build an Index.js with Modern JavaScript Features
- [Javascript] Monads
- [Javascript] Advanced Reduce: Additional Reducer Arguments
- [Javascript] Function scope
- 分享JavaScript获取网页关闭与取消关闭的事件
- JavaScript 库-localforage离线存储
- [Javascript] Prototype 1
- Javascript 学习 笔记三
- Javascript 学习 笔记二
- JavaScript 异步执行的学习笔记 - 什么是事件循环 Event loop?
- Javascript 事件propagation机制
- 计算Javascript 指定语句执行时间的两种办法
- 关于 JavaScript 事件循环 Event Loop 的一些理解
- JavaScript数字金额报错undefined (reading ‘toFixed‘)
- 从零开始学_JavaScript_系列(十一)——dojo(4)(GRID表格进阶:格式化、style、数据获取、多重排序、点击事件)
- JavaScript_BOM
- JavaScript中推断一个对象是否为"空对象”
- 【华为OD机试 2023】 过滤组合字符串(C++ Java JavaScript Python)
- javascript中常用的事件
- CEF(Chromium Embedded Framework和JavaScript交互相互调用函数和设置数据
- javascript --- 事件托付
- JavaScript实现禁用键盘和鼠标的点击事件
- 请写出JavaScript中常用的三种事件。
- Web前端 | JavaScript(事件)