JavaScript-事件循环
事件循环是允许在 javaScript 中执行显着性的机制,为i/o no封锁。我们知道JS是单线读物,即一次件事,并且需要处理需要时间在后台离开您的 call stack 的呼叫代码。
让我们浏览事件循环的概念,并通过允许布料来了解发生的事情。
引擎JavaScript
Enginea JavaScript是执行JavaScript的程序或解释器。引擎JavaScript可以作为标准解释器实现,也可以在适当的时间(即时)以某种方式编译bytecode的JavaScript。
JavaScript最著名的引擎是Google v8 ,它与 nodejs 相同,让我们从它开始,以下是以下的表示。
引擎由两个主要组件组成:
内存堆
呼叫堆栈执行代码时的堆栈帧在哪里。
运行时(执行时间)
几乎整个JavaScript开发人员使用的浏览器中的API(示例: settimeout )。但是,这些API并未由发动机提供。入口,它们来自哪里?
事实证明,现实有些复杂。
入口,我们有引擎,但实际上还有更多。我们有这些称为Web API的东西,这些内容由浏览器提供,例如礼物, ajax , settimeout 等等。p>
和入口,我们拥有流行的tâ£o 事件循环和回调队列。
致电堆栈(回电)
a 调用堆栈是一种基本存储在我们所在程序中的数据结构。如果我们输入功能,我们将其放在堆栈的顶部。如果我们从功能中返回,我们将从堆栈顶部撤出。这就是堆栈可以做的一切。
让我们看看一个示例。请参阅以下内容:
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
当引擎开始以这种方式执行时,呼叫堆栈将为空。然后,这些步骤将如下:
每个调用堆栈输入称为堆栈帧。
,这完全就像当异常是在异常发生时基本上是呼叫堆栈状态时构造的堆栈跟踪。 Dan A查看以下内容:
function foo() {
throw new Error("throw error here ...");
}
function bar() {
foo();
}
function start() {
bar();
}
start();
如果在Chrome处执行此操作,将产生以下堆栈跟踪:
“爆炸到stackâ达到呼叫堆栈的大小时会发生这种情况。而且可能很容易发生,尤其是如果您使用上诉£O而不经过非常广泛的测试,则会发生。
function foo() {
foo();
}
foo();
引擎时,它开始以这种方式执行,它开始调用fooâ。但是,此功能是递归的,并且开始自称,而没有任何条件结束。在执行的每个点中,一次又一次地将相同的功能添加到呼叫堆栈中。看起来这样:
但是,在某个时候,呼叫堆栈中的呼叫数量超过了呼叫堆栈的当前大小,浏览器决定采取措施,启动错误。 /p>
运行单线程可能非常狂热,因为您必须处理在多线程环境中创建的复杂场景,例如僵局。P>
但是,围绕单线程运行也非常有限。由于JavaScript有一个呼叫堆栈,因此当事情缓慢时会发生什么?
竞争和活动循环
当您在呼叫堆栈中有大量时间进行处理时会发生什么?例如,想象一下您想在浏览器中使用JavaScript对图像进行一些复杂的转换。
您可能会问您为什么这是一个问题?问题是,虽然Call stack具有执行功能,但浏览器无法做任何事情,但已阻止。这意味着浏览器无法渲染,无法执行任何其他方式。如果您想以自己的方式流动,这会造成问题。这不是问题。一旦浏览器开始处理呼叫堆栈上的许多任务,它就会停止响应很长时间。大多数浏览器通过创建错误采取行动,询问您是否要结束网页。
现在,这不是用户的最佳体验吗?
入口,我们如何在不阻止用户界面并未绕过浏览器的情况下执行重山雀?好吧,解决方案是 ashronous回调。
o事件循环
发动机不是孤立执行的,它是在A 托管环境中执行的,对于大多数开发人员来说,它是典型的 Web浏览器 strong>或 node.js strong>。目前,JavaScript已被整合到所有类型的设备中,从Robé到停机时间。每个设备代表引擎JS的不同类型的托管环境。
在所有环境中的共同点是一种称为事件循环的内部机制,它涉及程序随着时间的推移的执行,始终称为JS的引擎。
。这意味着引擎JS只是任何任意的按需执行环境。安排事件的周围环境(JS的执行)。
浏览器被配置为收听网络响应,当您有返回您的东西时,它将安排回调背景函数事件循环。。
让我们看看下图:
这些网络API是什么?从本质上讲,它们非常紧密,无法访问,您只能打电话给他们。它们是同时进入动作的浏览器的一部分。如果您是node.js开发人员,则这些是C ++的API。
入口,毕竟事件循环是什么?
事件循环有简单的工作来监视呼叫堆栈和回调队列。如果呼叫堆栈为空,它将在行中进行第一个事件,然后将其推入呼叫堆栈,该堆栈有效地执行它。
在事件循环中,这种迭代称为 tick 。每个事件只是一个回调函数。
让我们去以这种方式跟随并查看会发生什么:
console.log("Hi");
setTimeout(function cb1() {
console.log("cb1");
}, 5000);
console.log("Bye");
- 国家很明确。浏览器控制台清晰,呼叫堆栈为空。
-
添加
console.log('Hi')
â呼叫堆栈。 - 库里斯
-
console.log('Hi')
从呼叫堆中删除。 -
setTimeout(function cb1() { ... })
-
setTimeout(function cb1() { ... })
被执行。浏览器将创建一个计时器作为Web API的一部分。他会处理给您的倒计时。 -
setTimeout(function cb1() { ... })
这是完整的,并从呼叫堆栈中删除。 -
添加了
console.log('Bye')
。 -
console.log('Bye')
被执行。 -
console.log('Bye')
从呼叫堆栈中删除。 - 至少5000毫秒,计时器已完成,并将koud9呼叫返回发送到呼叫返回行。
- 事件循环从回调队列中删除
cb1
并将其发送给stack。 -
cb1
被执行并添加koud12ã呼叫堆栈。 -
console.log('cb1')
被执行。 -
console.log('cb1')
从呼叫堆栈中删除。 -
cb1
从呼叫堆栈中删除。
o es6 指定事件循环必须如何工作,这意味着它在技术上在发动机JS的责任范围内,而不是更不仅仅是执行适应环境的函数。 /p>
工作尾巴
如果循环循环,有一排处理的是 job queue 的微观任务,涉及 Promise 等异步,而宏观任务则由对待任务队列。
这是要观察到的一些要点:
- 并非所有任务都具有相同的优先级。有大杆菌和Microtareffes。
- 宏the称为
Tasks
,微型施加称为Jobs
。 - exemplos de macrotarefas圣£o settimeout , setInterval , setimmediate , i/o任务 ,et。
- Microtarefas soundemplos圣£o 承诺, process.nexttick 等。
- 事件中的队列包含MOS 任务(或宏观施法),称为任务队列。
- 事件循环中的线包含MOS Jobs (或Microtasks),称为 job queue 。
- 例如,承诺在 job queue 中, settimeout 的功能在任务Queue 中。<<<<<<<<<<<<<。 /li>
a 工作队列 prosui prioridade sobre a 任务队列 no 事件循环。
通常,事件循环在其乐团中获得了另一个要考虑的项目。让我们通过执行道路来理解上面的宽度。
const tom = () => console.log("Tom");
const jerry = () => console.log("Jerry");
const cartoon = () => {
console.log("Cartoon");
setTimeout(tom, 5000);
new Promise((resolve, reject) =>
resolve("should it be right after Tom, before Jerry?")
).then((resolve) => console.log(resolve));
jerry();
};
cartoon();
因此,预期的输出为
Cartoon
Jerry
should it be right after Tom, before Jerry?
Tom
执行流:
- fun -o
cartoon
entra na call stack。 - 它执行文本卡通的控制台日志。 Koud19 Web API叶子call call stack在以下执行行中,关联的功能
tom
放置在 taskqueue 中。 。
- 在以下执行行中,我们找到了 Promise 。诺言的回调在 Jobqueue 获得了一个地方。因此,在承诺中执行控制台日志的函数 Jobqueue 。
- 在以下执行行中,
jerry
函数放在堆栈上并执行。 - 我们在 Taskqueue 中有一个输入,而在 Jobqueue 中有另一个输入。事件循环优先考虑 Jobqueue 中的所有作业 taskqueue 中的任何内容。因此,从 promise 中的回调首先在呼叫堆栈中到达,执行,然后执行
tom
函数填充来自 taskqueue 的call stack 并执行。
在这里我们结束了与JavaScript相关的概念的研究。了解事件循环如何为我们创造更好,更优化的耳朵,对于那些想成为妈妈之上的程序员的人来说,这是一个非常重要的知识。
- 的链接参考和了解更多。
- - Como o Javascript funciona: O event loop
在 v8 和内存管理算法的内部操作中进行更多的深度转到此系列文章。。
这篇文章旨在帮助那些开始学习Web技术的人,除了作为我的学习中的激励措施并创建其他文章以修复学习。 em> sub>
给我一个咖啡馆? :) | pix: nascimento.dev.io@gmail.com