Javascript-單線程,非阻塞,異步,并發(fā)語言
恩,什么?我使用語言來完成工作。對于我和Javascript,此過程始于構(gòu)建一個小型游戲,ajax請求和表單驗證。我們與Hapi js的聯(lián)系越來越深。自從遇到React以來,我一直致力于?,F(xiàn)在,要成為一個更好的程序員,您必須問為什么事情如何進行。Javascript運行時對我來說是最大的奧秘之一。
什么是Javascript引擎和運行時?
Javascript運行時是指在運行JavaScript代碼時在何處執(zhí)行。就是說,可以在google chrome上執(zhí)行javascript,在這種情況下,您的javascript引擎是v8,如果在mozilla上-它是Spidermonkey,如果是IE-那么它的脈輪,如果是Safari-它是nitro,如果在節(jié)點上,則是v8?,F(xiàn)在什么是JS引擎,什么是JS運行時?
引擎將我們編寫的JavaScript轉(zhuǎn)換為機器代碼。所有JavaScript引擎都實現(xiàn)ECMAScript提供的語言規(guī)范。標準化促進了獨立引擎的開發(fā),并確保您的腳本無論在何處運行都可以得到相同的結(jié)果。為了獲得速度,V8將JavaScript代碼轉(zhuǎn)換為更有效的機器代碼,而不是使用解釋器。它通過像許多現(xiàn)代JavaScript引擎(例如SpiderMonkey或Rhino(Mozilla))一樣實現(xiàn)JIT(即時)編譯器,在執(zhí)行時將JavaScript代碼編譯為機器代碼。這里的主要區(qū)別是V8不會產(chǎn)生字節(jié)碼或任何中間碼。JavaScript引擎只是更大概念的組成部分。該引擎在稱為Javascript Runtime的環(huán)境中工作,該環(huán)境為我們的腳本提供了附加功能。這些功能可能包括撥打網(wǎng)絡(luò)電話,捕獲鼠標/鍵盤事件等。
這是JS Runtime的體系結(jié)構(gòu)。V8沒有這些WebAPI。這些由運行時給出。在chrome瀏覽器JS運行時中,瀏覽器擁有它,而在Node中則由C ++庫提供。
> Runtime Architecture
讓我們看看Javascript是如何異步和單線程的。
單線程,什么?
Javascript代碼在單線程中執(zhí)行,但是Javascript運行時不在單線程中運行。線程池存在于JS運行時中,但是我們不必擔心它,因為運行時會處理它。但是,那是怎么做的呢?事件循環(huán)可以挽救。
讓我們了解什么是運行時(或?qū)儆谶\行時的JS引擎)中的堆和調(diào)用堆棧。javascript代碼首先轉(zhuǎn)換為機器代碼。堆存儲所有變量,并由調(diào)用堆棧執(zhí)行操作。
- console.log("Start")
- function sayHello(name) {
- console.log(`Hello ${name}!`)
- }
- sayHello("Abhinav");
- console.log("End")
所有這些都轉(zhuǎn)到調(diào)用堆棧并在那里執(zhí)行。
- Start
- Hello Abhinav
- End
我們可以將腳本分為兩種類型,即立即調(diào)用和稍后調(diào)用。
異步任務(wù)到來時會發(fā)生什么?任務(wù)需要時間才能運行。比如說進行API調(diào)用或計時器等。有一個稱為回調(diào)的概念。這是完成此任務(wù)后要執(zhí)行的功能。
好吧,它們作為任何常規(guī)函數(shù)進入調(diào)用堆棧,但是由于此任務(wù)駐留在WebAPI中,因此我們對WebAPI進行了調(diào)用。它存儲任務(wù)的回調(diào)函數(shù)并為我們完成任務(wù)(根據(jù)運行時使用線程/多處理)。任務(wù)完成后,它將回調(diào)發(fā)送到回調(diào)隊列。
在這里再次可視化。
現(xiàn)在什么是事件循環(huán)?事件循環(huán)連續(xù)運行(在瀏覽器運行時中,它并不總是在節(jié)點中運行)以檢查調(diào)用棧是否為空,如果調(diào)用棧為空,它將從回調(diào)隊列中提取第一項并將其移至調(diào)用棧并執(zhí)行回調(diào)函數(shù)。在堆棧不為空之前,不會從回調(diào)隊列添加任何功能。
回調(diào)總是完全執(zhí)行的。事件循環(huán)一次運行一個回調(diào)。沒有上下文切換。隊列中的所有回調(diào)都必須等到當前的回調(diào)完成。如果腳本運行時間過長,則會阻止其他腳本。這就是為什么回調(diào)應(yīng)該相對簡短而簡單。
很簡單吧!但實際上,它要復(fù)雜得多。有多個隊列,具體取決于運行時,并且它們的優(yōu)先級不同。有一些東西作為渲染隊列。誰的工作是渲染屏幕。
非阻塞狀態(tài)如何?
假設(shè)您在調(diào)用API時失敗,或者發(fā)生了其他事件,該事件仍然存在于Web api中,因此它永遠不會進入回調(diào)隊列,因此不會進入調(diào)用堆棧。因此,沒有任何東西被阻止。
它是并發(fā)的嗎?
并行和并行有什么區(qū)別?并行是您同時執(zhí)行2個任務(wù)的位置。(邊吃爆米花邊看電影)。這是通過多核來實現(xiàn)的。JS代碼在調(diào)用堆棧中并行執(zhí)行,而不是并行執(zhí)行。但是WebAPI可以利用多核并并行運行。
原文鏈接:
https://theflyingmantis.medium.com/javascript-single-threaded-non-blocking-asynchronous-concurrent-language-ffae97c57bef)