关于 JavaScript 事件循环 Event Loop 的一些理解

简介: 浏览器 JavaScript 执行流程以及在 Node.js 中都是基于事件循环的。

浏览器 JavaScript 执行流程以及在 Node.js 中都是基于事件循环的。


了解事件循环的工作原理对于正确编写健壮和高性能的 JavaScript 代码非常重要。


本文首先介绍有关事物如何工作的理论细节,然后介绍这些知识的实际应用。


事件循环遵循下面的处理范式:


任务被设置——引擎处理它们——然后等待更多任务(在睡眠和消耗接近于零的 CPU 事件)。


如果在 JavaScript 执行引擎忙时又有新任务达到,这些新任务会被排队,形成一个队列,即所谓的 宏任务队列(v8 术语)。

image.png

例如,当引擎忙于执行脚本时,用户可能会移动鼠标导致 mousemove,setTimeout 可能会到期等等,这些任务形成一个队列,如上图所示。


队列中的任务以 先到先处理 的方式被引擎处理。 当引擎浏览器完成脚本后,它会处理 mousemove 事件,然后是 setTimeout 处理程序,等等。


注意以下两点:

  1. 当引擎执行任务时,渲染永远不会发生。 任务是否需要很长时间并不重要。 仅在任务完成后才绘制对 DOM 的更改。
  2. 如果一项任务花费的时间太长,浏览器就无法执行其他任务,例如处理用户事件。 所以一段时间后,浏览器会发出 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();



目录
相关文章
|
4月前
|
消息中间件 存储 前端开发
JavaScript高级主题:解释一下 JavaScript 中的事件循环(Event Loop)。
JavaScript高级主题:解释一下 JavaScript 中的事件循环(Event Loop)。
38 0
|
Web App开发 前端开发 JavaScript
【朴灵评注】JavaScript 运行机制详解:再谈Event Loop
PS: 我先旁观下大师们的讨论,得多看书了~ 别人说的:“看了一下不觉得评注对到哪里去,只有吹毛求疵之感。 比如同步异步介绍,本来就无大错;比如node图里面的OS operation,推敲一下就可以猜到那是指同步操作(自然不走event loop了);至于watcher啥的,显然只是实现上的特色,即使用同一个queue实现也未尝不可” 【原帖: 
3071 0
|
10天前
|
存储 JavaScript 前端开发
JS的执行原理,一文了解Event Loop事件循环、微任务、宏任务
了解JavaScript的事件循环和任务队列对于处理异步任务至关重要。事件循环由主线程和任务队列组成,当主线程执行完同步任务后,会检查任务队列,按顺序执行宏任务和微任务。宏任务包括`setTimeout`等,微任务如`Promise`的回调。在实际开发中,事件循环保证了代码的非阻塞执行,提高了用户体验。例如,`setTimeout`的回调会在当前宏任务结束后,所有微任务执行完才会执行。理解这一机制对于解决面试中的异步问题非常有帮助。
13 0
JS的执行原理,一文了解Event Loop事件循环、微任务、宏任务
|
8月前
|
移动开发 JavaScript 前端开发
说说你对事件循环event loop的理解?
说说你对事件循环event loop的理解?
71 0
|
9月前
|
JavaScript 前端开发 API
(译)看得见的 JavaScript:事件循环(Event Loop)
(译)看得见的 JavaScript:事件循环(Event Loop)
68 1
|
5月前
|
JavaScript 前端开发
javascript event 事件
javascript event 事件
24 0
|
7月前
|
JavaScript 前端开发
关于 JavaScript 事件循环 Event Loop 的一些理解
关于 JavaScript 事件循环 Event Loop 的一些理解
44 0
|
8月前
|
前端开发 JavaScript 小程序
JavaScript 中的异步:Event Loop 及其他
JavaScript 中的异步:Event Loop 及其他
52 0
|
8月前
|
JavaScript 前端开发
说说你对事件循环的理解(event loop)
说说你对事件循环的理解(event loop)
|
9月前
|
移动开发 JavaScript 前端开发
Event Loop 事件循环简介
Event Loop 事件循环简介
99 0