恩,什么?我使用语言来完成工作。对于我和Javascript,此过程始于构建一个小型游戏,ajax请求和表单验证。我们与Hapi js的联系越来越深。自从遇到React以来,我一直致力于。现在,要成为一个更好的程序员,您必须问为什么事情如何进行。Javascript运行时对我来说是最大的奥秘之一。
什么是Javascript引擎和运行时?
Javascript运行时是指在运行JavaScript代码时在何处执行。就是说,可以在google chrome上执行javascript,在这种情况下,您的javascript引擎是v8,如果在mozilla上-它是Spidermonkey,如果是IE-那么它的脉轮,如果是Safari-它是nitro,如果在节点上,则是v8。现在什么是JS引擎,什么是JS运行时?
引擎将我们编写的JavaScript转换为机器代码。所有JavaScript引擎都实现ECMAScript提供的语言规范。标准化促进了独立引擎的开发,并确保您的脚本无论在何处运行都可以得到相同的结果。为了获得速度,V8将JavaScript代码转换为更有效的机器代码,而不是使用解释器。它通过像许多现代JavaScript引擎(例如SpiderMonkey或Rhino(Mozilla))一样实现JIT(即时)编译器,在执行时将JavaScript代码编译为机器代码。这里的主要区别是V8不会产生字节码或任何中间码。JavaScript引擎只是更大概念的组成部分。该引擎在称为Javascript Runtime的环境中工作,该环境为我们的脚本提供了附加功能。这些功能可能包括拨打网络电话,捕获鼠标/键盘事件等。
这是JS Runtime的体系结构。V8没有这些WebAPI。这些由运行时给出。在chrome浏览器JS运行时中,浏览器拥有它,而在Node中则由C ++库提供。
> Runtime Architecture
让我们看看Javascript是如何异步和单线程的。
单线程,什么?
Javascript代码在单线程中执行,但是Javascript运行时不在单线程中运行。线程池存在于JS运行时中,但是我们不必担心它,因为运行时会处理它。但是,那是怎么做的呢?事件循环可以挽救。
让我们了解什么是运行时(或属于运行时的JS引擎)中的堆和调用堆栈。javascript代码首先转换为机器代码。堆存储所有变量,并由调用堆栈执行操作。
- console.log("Start")
- function sayHello(name) {
- console.log(`Hello ${name}!`)
- }
- sayHello("Abhinav");
- console.log("End")
所有这些都转到调用堆栈并在那里执行。
- Start
- Hello Abhinav
- End
我们可以将脚本分为两种类型,即立即调用和稍后调用。
异步任务到来时会发生什么?任务需要时间才能运行。比如说进行API调用或计时器等。有一个称为回调的概念。这是完成此任务后要执行的功能。
好吧,它们作为任何常规函数进入调用堆栈,但是由于此任务驻留在WebAPI中,因此我们对WebAPI进行了调用。它存储任务的回调函数并为我们完成任务(根据运行时使用线程/多处理)。任务完成后,它将回调发送到回调队列。
在这里再次可视化。
现在什么是事件循环?事件循环连续运行(在浏览器运行时中,它并不总是在节点中运行)以检查调用栈是否为空,如果调用栈为空,它将从回调队列中提取第一项并将其移至调用栈并执行回调函数。在堆栈不为空之前,不会从回调队列添加任何功能。
回调总是完全执行的。事件循环一次运行一个回调。没有上下文切换。队列中的所有回调都必须等到当前的回调完成。如果脚本运行时间过长,则会阻止其他脚本。这就是为什么回调应该相对简短而简单。
很简单吧!但实际上,它要复杂得多。有多个队列,具体取决于运行时,并且它们的优先级不同。有一些东西作为渲染队列。谁的工作是渲染屏幕。
非阻塞状态如何?
假设您在调用API时失败,或者发生了其他事件,该事件仍然存在于Web api中,因此它永远不会进入回调队列,因此不会进入调用堆栈。因此,没有任何东西被阻止。
它是并发的吗?
并行和并行有什么区别?并行是您同时执行2个任务的位置。(边吃爆米花边看电影)。这是通过多核来实现的。JS代码在调用堆栈中并行执行,而不是并行执行。但是WebAPI可以利用多核并并行运行。
原文链接:
https://theflyingmantis.medium.com/javascript-single-threaded-non-blocking-asynchronous-concurrent-language-ffae97c57bef)