摘要:最受歡迎的引擎是,由和使用,用于,以及使用的。引擎它們是如何工作的全局執(zhí)行上下文和調(diào)用堆棧剛剛了解了引擎如何讀取變量和函數(shù)聲明,它們最終被放入了全局內(nèi)存堆中。事件循環(huán)只有一個(gè)任務(wù)它檢查調(diào)用堆棧是否為空。
為了保證可讀性,本文采用意譯而非直譯。
想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你!
有沒(méi)有想過(guò)瀏覽器如何讀取和運(yùn)行JS代碼? 這看起來(lái)很神奇,我們可以通過(guò)瀏覽器提供的控制臺(tái)來(lái)了解背后的一些原理。
在Chrome中打開(kāi)瀏覽器控制臺(tái),然后查看Sources這欄,在右側(cè)可以到一個(gè) Call Stack 盒子。
JS 引擎是一個(gè)可以編譯和解釋我們的JS代碼強(qiáng)大的組件。 最受歡迎的JS 引擎是V8,由 Google Chrome 和 Node.j s使用,SpiderMonkey 用于Firefox,以及Safari/WebKit使用的 JavaScriptCore。
雖然現(xiàn)在 JS 引擎不是幫我們處理全面的工作。但是每個(gè)引擎中都有一些較小的組件為我們做繁瑣的的工作。
其中一個(gè)組件是調(diào)用堆棧(Call Stack),與全局內(nèi)存和執(zhí)行上下文一起運(yùn)行我們的代碼。
Js 引擎和全局內(nèi)存(Global Memory)JavaScript 是編譯語(yǔ)言同時(shí)也是解釋語(yǔ)言。信不信由你,JS 引擎在執(zhí)行代碼之前只需要幾微秒就能編譯代碼。
這聽(tīng)起來(lái)很神奇,對(duì)吧?這種神奇的功能稱(chēng)為JIT(及時(shí)編譯)。這個(gè)是一個(gè)很大的話(huà)題,一本書(shū)都不足以描述JIT是如何工作的。但現(xiàn)在,我們午飯可以跳過(guò)編譯背后的理論,將重點(diǎn)放在執(zhí)行階段,盡管如此,這仍然很有趣。
考慮以下代碼:
var num = 2; function pow(num) { return num * num; }
如果問(wèn)你如何在瀏覽器中處理上述代碼? 你會(huì)說(shuō)些什么? 你可能會(huì)說(shuō)“瀏覽器讀取代碼”或“瀏覽器執(zhí)行代碼”。
現(xiàn)實(shí)比這更微妙。首先,讀取這段代碼的不是瀏覽器,是JS引擎。JS引擎讀取代碼,一旦遇到第一行,就會(huì)將幾個(gè)引用放入全局內(nèi)存。
全局內(nèi)存(也稱(chēng)為堆)JS引擎保存變量和函數(shù)聲明的地方。因此,回到上面示例,當(dāng) JS引擎讀取上面的代碼時(shí),全局內(nèi)存中放入了兩個(gè)綁定。
即使示例只有變量和函數(shù),也要考慮你的JS代碼在更大的環(huán)境中運(yùn)行:在瀏覽器中或在Node.js中。 在這些環(huán)境中,有許多預(yù)定義的函數(shù)和變量,稱(chēng)為全局變量。 全球記憶將比num和pow更多。
上例中,沒(méi)有執(zhí)行任何操作,但是如果我們像這樣運(yùn)行函數(shù)會(huì)怎么樣呢:
var num = 2; function pow(num) { return num * num; } pow(num);
現(xiàn)在事情變得有趣了。當(dāng)函數(shù)被調(diào)用時(shí),JavaScript引擎會(huì)為全局執(zhí)行上下文和調(diào)用棧騰出空間。
JS引擎:它們是如何工作的? 全局執(zhí)行上下文和調(diào)用堆棧剛剛了解了 JS引擎如何讀取變量和函數(shù)聲明,它們最終被放入了全局內(nèi)存(堆)中。
但現(xiàn)在我們執(zhí)行了一個(gè)JS函數(shù),JS引擎必須處理它。怎么做?每個(gè)JS引擎中都有一個(gè)基本組件,叫調(diào)用堆棧。
調(diào)用堆棧是一個(gè)堆棧數(shù)據(jù)結(jié)構(gòu):這意味著元素可以從頂部進(jìn)入,但如果它們上面有一些元素,它們就不能離開(kāi),JS 函數(shù)就是這樣的。
一旦執(zhí)行,如果其他函數(shù)仍然被阻塞,它們就不能離開(kāi)調(diào)用堆棧。請(qǐng)注意,這個(gè)有助于你理解“JavaScript是單線(xiàn)程的”這句話(huà)。
回到我們的例子,當(dāng)函數(shù)被調(diào)用時(shí),JS引擎將該函數(shù)推入調(diào)用堆棧
同時(shí),JS 引擎還分配了一個(gè)全局執(zhí)行上下文,這是運(yùn)行JS代碼的全局環(huán)境,如下所示
想象全局執(zhí)行上下文是一個(gè)海洋,其中全局函數(shù)像魚(yú)一樣游動(dòng),多美好! 但現(xiàn)實(shí)遠(yuǎn)非那么簡(jiǎn)單, 如果我函數(shù)有一些嵌套變量或一個(gè)或多個(gè)內(nèi)部函數(shù)怎么辦?
即使是像下面這樣的簡(jiǎn)單變化,JS引擎也會(huì)創(chuàng)建一個(gè)本地執(zhí)行上下文:
var num = 2; function pow(num) { var fixed = 89; return num * num; } pow(num);
注意,我在pow函數(shù)中添加了一個(gè)名為fixed的變量。在這種情況下,pow函數(shù)中會(huì)創(chuàng)建一個(gè)本地執(zhí)行上下文,fixed 變量被放入pow函數(shù)中的本地執(zhí)行上下文中。
對(duì)于嵌套函數(shù)的每個(gè)嵌套函數(shù),引擎都會(huì)創(chuàng)建更多的本地執(zhí)行上下文。
JavaScript 是單線(xiàn)程和其他有趣的故事JavaScript是單線(xiàn)程的,因?yàn)橹挥幸粋€(gè)調(diào)用堆棧處理我們的函數(shù)。也就是說(shuō),如果有其他函數(shù)等待執(zhí)行,函數(shù)就不能離開(kāi)調(diào)用堆棧。
在處理同步代碼時(shí),這不是問(wèn)題。例如,兩個(gè)數(shù)字之間的和是同步的,以微秒為單位。但如果涉及異步的時(shí)候,怎么辦呢?
幸運(yùn)的是,默認(rèn)情況下JS引擎是異步的。即使它一次執(zhí)行一個(gè)函數(shù),也有一種方法可以讓外部(如:瀏覽器)執(zhí)行速度較慢的函數(shù),稍后探討這個(gè)主題。
當(dāng)瀏覽器加載某些JS代碼時(shí),JS引擎會(huì)逐行讀取并執(zhí)行以下步驟:
將變量和函數(shù)的聲明放入全局內(nèi)存(堆)中
將函數(shù)的調(diào)用放入調(diào)用堆棧
創(chuàng)建全局執(zhí)行上下文,在其中執(zhí)行全局函數(shù)
創(chuàng)建多個(gè)本地執(zhí)行上下文(如果有內(nèi)部變量或嵌套函數(shù))
到目前為止,對(duì)JS引擎的同步機(jī)制有了基本的了解。 在接下來(lái)的部分中,講講 JS 異步工作原理。
異步JS,回調(diào)隊(duì)列和事件循環(huán)全局內(nèi)存(堆),執(zhí)行上下文和調(diào)用堆棧解釋了同步 JS 代碼在瀏覽器中的運(yùn)行方式。 然而,我們遺漏了一些東西,當(dāng)有一些異步函數(shù)運(yùn)行時(shí)會(huì)發(fā)生什么?
請(qǐng)記住,調(diào)用堆棧一次可以執(zhí)行一個(gè)函數(shù),甚至一個(gè)阻塞函數(shù)也可以直接凍結(jié)瀏覽器。 幸運(yùn)的是JavaScript引擎是聰明的,并且在瀏覽器的幫助下可以解決問(wèn)題。
當(dāng)我們運(yùn)行一個(gè)異步函數(shù)時(shí),瀏覽器接受該函數(shù)并運(yùn)行它??紤]如下代碼:
setTimeout(callback, 10000); function callback(){ console.log("hello timer!"); }
setTimeout 大家都知道得用得很多次了,但你可能不知道它不是內(nèi)置的JS函數(shù)。 也就是說(shuō),當(dāng)JS 出現(xiàn),語(yǔ)言中沒(méi)有內(nèi)置的setTimeout。
setTimeout瀏覽器API( Browser API)的一部分,它是瀏覽器免費(fèi)提供給我們的一組方便的工具。這在實(shí)戰(zhàn)中意味著什么?由于setTimeout是一個(gè)瀏覽器的一個(gè)Api,函數(shù)由瀏覽器直接運(yùn)行(它會(huì)在調(diào)用堆棧中出現(xiàn)一會(huì)兒,但會(huì)立即刪除)。
10秒后,瀏覽器接受我們傳入的回調(diào)函數(shù)并將其移動(dòng)到回調(diào)隊(duì)列(Callback Queu)中。??紤]以下代碼
var num = 2; function pow(num) { return num * num; } pow(num); setTimeout(callback, 10000); function callback(){ console.log("hello timer!"); }
示意圖如下:
如你所見(jiàn),setTimeout在瀏覽器上下文中運(yùn)行。 10秒后,計(jì)時(shí)器被觸發(fā),回調(diào)函數(shù)準(zhǔn)備運(yùn)行。 但首先它必須通過(guò)回調(diào)隊(duì)列(Callback Queue)。 回調(diào)隊(duì)列是一個(gè)隊(duì)列數(shù)據(jù)結(jié)構(gòu),回調(diào)隊(duì)列是一個(gè)有序的函數(shù)隊(duì)列。
每個(gè)異步函數(shù)在被放入調(diào)用堆棧之前必須通過(guò)回調(diào)隊(duì)列,但這個(gè)工作是誰(shuí)做的呢,那就是事件循環(huán)(Event Loop)。
事件循環(huán)只有一個(gè)任務(wù):它檢查調(diào)用堆棧是否為空。如果回調(diào)隊(duì)列中(Callback Queue)有某個(gè)函數(shù),并且調(diào)用堆棧是空閑的,那么就將其放入調(diào)用堆棧中。
完成后,執(zhí)行該函數(shù)。 以下是用于處理異步和同步代碼的JS引擎的圖:
想象一下,callback() 已準(zhǔn)備好執(zhí)行,當(dāng) pow() 完成時(shí),調(diào)用堆棧(Call Stack) 為空,事件循環(huán)(Event Look) 將 callback() 放入調(diào)用堆中。大概就是這樣,如果你理解了上面的插圖,那么你就可以理解所有的JavaScript了。
回調(diào)地獄和 ES6 中的PromisesJS 中回調(diào)函數(shù)無(wú)處不在,它們用于同步和異步代碼。 考慮如下map方法:
function mapper(element){ return element * 2; } [1, 2, 3, 4, 5].map(mapper);
mapper是一個(gè)在map內(nèi)部傳遞的回調(diào)函數(shù)。上面的代碼是同步的,考慮異步的情況:
function runMeEvery(){ console.log("Ran!"); } setInterval(runMeEvery, 5000);
該代碼是異步的,我們?cè)?b>setInterval中傳遞回調(diào)runMeEvery?;卣{(diào)在JS中無(wú)處不在,因此就會(huì)出現(xiàn)了一個(gè)問(wèn)題:回調(diào)地獄。
JavaScript 中的回調(diào)地獄指的是一種編程風(fēng)格,其中回調(diào)嵌套在回調(diào)函數(shù)中,而回調(diào)函數(shù)又嵌套在其他回調(diào)函數(shù)中。由于 JS 異步特性,js 程序員多年來(lái)陷入了這個(gè)陷阱。
說(shuō)實(shí)話(huà),我從來(lái)沒(méi)有遇到過(guò)極端的回調(diào)金字塔,這可能是因?yàn)槲抑匾暱勺x代碼,而且我總是堅(jiān)持這個(gè)原則。如果你在遇到了回調(diào)地獄的問(wèn)題,說(shuō)明你的函數(shù)做得太多。
這里不會(huì)討論回調(diào)地獄,如果你好奇,有一個(gè)網(wǎng)站,callbackhell.com,它更詳細(xì)地探索了這個(gè)問(wèn)題,并提供了一些解決方案。
我們現(xiàn)在要關(guān)注的是ES6的 Promises。ES6 Promises是JS語(yǔ)言的一個(gè)補(bǔ)充,旨在解決可怕的回調(diào)地獄。但什么是 Promises 呢?
JS的 Promise是未來(lái)事件的表示。 Promise 可以以成功結(jié)束:用行話(huà)說(shuō)我們已經(jīng)解決了resolved(fulfilled)。 但如果 Promise 出錯(cuò),我們會(huì)說(shuō)它處于拒絕(rejected )狀態(tài)。 Promise 也有一個(gè)默認(rèn)狀態(tài):每個(gè)新的 Promise 都以掛起(pending)狀態(tài)開(kāi)始。
創(chuàng)建和使用 JavaScript 的 Promises要?jiǎng)?chuàng)建一個(gè)新的 Promise,可以通過(guò)傳遞回調(diào)函數(shù)來(lái)調(diào)用 Promise 構(gòu)造函數(shù)?;卣{(diào)函數(shù)可以接受兩個(gè)參數(shù):resolve和reject。如下所示:
const myPromise = new Promise(function(resolve){ setTimeout(function(){ resolve() }, 5000) });
如下所示,resolve是一個(gè)函數(shù),調(diào)用它是為了使Promise 成功,別外也可以使用 reject 來(lái)表示調(diào)用失敗。
const myPromise = new Promise(function(resolve, reject){ setTimeout(function(){ reject() }, 5000) });
注意,在第一個(gè)示例中可以省略reject,因?yàn)樗堑诙€(gè)參數(shù)。但是,如果打算使用reject,則不能忽略resolve,如下所示,最終將得到一個(gè)resolved 的承諾,而非 reject。
// 不能忽略 resolve ! const myPromise = new Promise(function(reject){ setTimeout(function(){ reject() }, 5000) });
現(xiàn)在,Promises看起來(lái)并不那么有用,我們可以向它添加一些數(shù)據(jù),如下所示:
const myPromise = new Promise(function(resolve) { resolve([{ name: "Chris" }]); });
但我們?nèi)匀豢床坏饺魏螖?shù)據(jù)。 要從Promise中提取數(shù)據(jù),需要鏈接一個(gè)名為then的方法。 它需要一個(gè)回調(diào)來(lái)接收實(shí)際數(shù)據(jù):
const myPromise = new Promise(function(resolve, reject) { resolve([{ name: "Chris" }]); }); myPromise.then(function(data) { console.log(data); });Promises 的錯(cuò)誤處理
對(duì)于同步代碼而言,JS 錯(cuò)誤處理大都很簡(jiǎn)單,如下所示:
function makeAnError() { throw Error("Sorry mate!"); } try { makeAnError(); } catch (error) { console.log("Catching the error! " + error); }
將會(huì)輸出:
Catching the error! Error: Sorry mate!
現(xiàn)在嘗試使用異步函數(shù):
function makeAnError() { throw Error("Sorry mate!"); } try { setTimeout(makeAnError, 5000); } catch (error) { console.log("Catching the error! " + error);
由于setTimeout,上面的代碼是異步的,看看運(yùn)行會(huì)發(fā)生什么:
throw Error("Sorry mate!"); ^ Error: Sorry mate! at Timeout.makeAnError [as _onTimeout] (/home/valentino/Code/piccolo-javascript/async.js:2:9)
這次的輸出是不同的。錯(cuò)誤沒(méi)有通過(guò)catch塊,它可以自由地在堆棧中向上傳播。
那是因?yàn)?b>try/catch僅適用于同步代碼。 如果你很好奇,Node.js中的錯(cuò)誤處理會(huì)詳細(xì)解釋這個(gè)問(wèn)題。
幸運(yùn)的是,Promise 有一種處理異步錯(cuò)誤的方法,就像它們是同步的一樣:
const myPromise = new Promise(function(resolve, reject) { reject("Errored, sorry!"); });
在上面的例子中,我們可以使用catch處理程序處理錯(cuò)誤:
const myPromise = new Promise(function(resolve, reject) { reject("Errored, sorry!"); }); myPromise.catch(err => console.log(err));
我們也可以調(diào)用Promise.reject()來(lái)創(chuàng)建和拒絕一個(gè)Promise
Promise.reject({msg: "Rejected!"}).catch(err => console.log(err));Promises 組合:Promise.all,Promise.allSettled, Promise.any
Promise API 提供了許多將Promise組合在一起的方法。 其中最有用的是Promise.all,它接受一個(gè)Promises數(shù)組并返回一個(gè)Promise。 如果參數(shù)中 promise 有一個(gè)失?。╮ejected),此實(shí)例回調(diào)失?。╮eject),失敗原因的是第一個(gè)失敗 promise 的結(jié)果。
Promise.race(iterable) 方法返回一個(gè) promise,一旦迭代器中的某個(gè)promise解決或拒絕,返回的 promise就會(huì)解決或拒絕。
較新版本的V8也將實(shí)現(xiàn)兩個(gè)新的組合:Promise.allSettled和Promise.any。 Promise.any仍然處于提案的早期階段:在撰寫(xiě)本文時(shí),仍然沒(méi)有瀏覽器支持它。
Promise.any可以表明任何Promise是否fullfilled。 與 Promise.race的區(qū)別在于Promise.any不會(huì)拒絕即使其中一個(gè)Promise被拒絕。
無(wú)論如何,兩者中最有趣的是 Promise.allSettled,它也是 Promise 數(shù)組,但如果其中一個(gè)Promise拒絕,它不會(huì)短路。 當(dāng)你想要檢查Promise數(shù)組是否全部已解決時(shí),它是有用的,無(wú)論最終是否拒絕,可以把它想象成Promise.all 的反對(duì)者。
異步進(jìn)化:從Promises 到 async/awaitECMAScript 2017 (ES8)的出現(xiàn),推出了新的語(yǔ)法誕生了async/await。
async/await只是Promise 語(yǔ)法糖。它只是一種基于Promises編寫(xiě)異步代碼的新方法, async/await 不會(huì)以任何方式改變JS,請(qǐng)記住,JS必須向后兼容舊瀏覽器,不應(yīng)破壞現(xiàn)有代碼。
來(lái)個(gè)例子:
const myPromise = new Promise(function(resolve, reject) { resolve([{ name: "Chris" }]); }); myPromise.then((data) => console.log(data))
使用async/await, 我們可以將Promise包裝在標(biāo)記為async的函數(shù)中,然后等待結(jié)果的返回:
const myPromise = new Promise(function(resolve, reject) { resolve([{ name: "Chris" }]); }); async function getData() { const data = await myPromise; console.log(data); } getData();
有趣的是,async 函數(shù)也會(huì)返回Promise,你也可以這樣做:
async function getData() { const data = await myPromise; return data; } getData().then(data => console.log(data));
那如何處理錯(cuò)誤? async/await提一個(gè)好處就是可以使用try/catch。 再看一下Promise,我們使用catch處理程序來(lái)處理錯(cuò)誤:
const myPromise = new Promise(function(resolve, reject) { reject("Errored, sorry!"); }); myPromise.catch(err => console.log(err));
使用async函數(shù),我們可以重構(gòu)以上代碼:
async function getData() { try { const data = await myPromise; console.log(data); // or return the data with return data } catch (error) { console.log(error); } } getData();
并不是每個(gè)人都喜歡這種風(fēng)格。try/catch會(huì)使代碼變得冗長(zhǎng),在使用try/catch時(shí),還有另一個(gè)怪異的地方需要指出,如下所示:
async function getData() { try { if (true) { throw Error("Catch me if you can"); } } catch (err) { console.log(err.message); } } getData() .then(() => console.log("I will run no matter what!")) .catch(() => console.log("Catching err"));
運(yùn)行結(jié)果:
以上兩個(gè)字符串都會(huì)打印。 請(qǐng)記住, try/catch 是一個(gè)同步構(gòu)造,但我們的異步函數(shù)產(chǎn)生一個(gè)Promise。 他們?cè)趦蓷l不同的軌道上行駛,比如兩列火車(chē)。但他們永遠(yuǎn)不會(huì)見(jiàn)面, 也就是說(shuō),throw 拋出的錯(cuò)誤永遠(yuǎn)不會(huì)觸發(fā)getData()的catch方法。
實(shí)戰(zhàn)中,我們不希望throw觸then的處理程序。 一種的解決方案是從函數(shù)返回Promise.reject():
async function getData() { try { if (true) { return Promise.reject("Catch me if you can"); } } catch (err) { console.log(err.message); } }
現(xiàn)在按預(yù)期處理錯(cuò)誤
getData() .then(() => console.log("I will NOT run no matter what!")) .catch(() => console.log("Catching err")); "Catching err" // 輸出
除此之外,async/await似乎是在JS中構(gòu)建異步代碼的最佳方式。 我們可以更好地控制錯(cuò)誤處理,代碼看起來(lái)也更清晰。
總結(jié)JS 是一種用于Web的腳本語(yǔ)言,具有先編譯然后由引擎解釋的特性。 在最流行的JS引擎中,有谷歌Chrome和Node.js使用的V8,有Firefox構(gòu)建的SpiderMonkey,以及Safari使用的JavaScriptCore。
JS引擎包含很有組件:調(diào)用堆棧、全局內(nèi)存(堆)、事件循環(huán)、回調(diào)隊(duì)列。所有這些組件一起工作,完美地進(jìn)行了調(diào)優(yōu),以處理JS中的同步和異步代碼。
JS引擎是單線(xiàn)程的,這意味著運(yùn)行函數(shù)只有一個(gè)調(diào)用堆棧。這一限制是JS異步本質(zhì)的基礎(chǔ):所有需要時(shí)間的操作都必須由外部實(shí)體(例如瀏覽器)或回調(diào)函數(shù)負(fù)責(zé)。
為了簡(jiǎn)化異步代碼流,ECMAScript 2015 給我們帶來(lái)了Promise。 Promise 是一個(gè)異步對(duì)象,用于表示任何異步操作的失敗或成功。 但改進(jìn)并沒(méi)有止步于此。 在2017年,async/ await誕生了:它是Promise的一種風(fēng)格彌補(bǔ),使得編寫(xiě)異步代碼成為可能,就好像它是同步的一樣。
代碼部署后可能存在的BUG沒(méi)法實(shí)時(shí)知道,事后為了解決這些BUG,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具 Fundebug。
交流干貨系列文章匯總?cè)缦?,覺(jué)得不錯(cuò)點(diǎn)個(gè)Star,歡迎 加群 互相學(xué)習(xí)。
https://github.com/qq44924588...
我是小智,公眾號(hào)「大遷世界」作者,對(duì)前端技術(shù)保持學(xué)習(xí)愛(ài)好者。我會(huì)經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!
關(guān)注公眾號(hào),后臺(tái)回復(fù)福利,即可看到福利,你懂的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105180.html
摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推入調(diào)用堆棧。執(zhí)行從調(diào)用堆棧中移除從調(diào)用堆棧中移除快速回顧值得注意的是,指定了事件循環(huán)應(yīng)該如何工作,這意味著在技術(shù)上它屬于引擎的職責(zé)范圍,不再僅僅扮演宿主環(huán)境的角色。 此篇是 JavaScript是如何工作的第四篇,其它三篇可以看這里: JavaScript是如何工作的:引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述! JavaScript是如何工作的:深入V8引擎&編寫(xiě)...
摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推送到調(diào)用堆棧。如何工作請(qǐng)注意,不會(huì)自動(dòng)將您的回調(diào)函數(shù)放到事件循環(huán)隊(duì)列中。它設(shè)置了一個(gè)計(jì)時(shí)器,當(dāng)計(jì)時(shí)器到期時(shí),環(huán)境將您的回調(diào)函數(shù)放入事件循環(huán)中,以便將來(lái)的某個(gè)事件會(huì)將其選中并執(zhí)行它。 我們將通過(guò)回顧第一篇文章中單線(xiàn)程編程的缺點(diǎn),然后在討論如何克服它們來(lái)構(gòu)建令人驚嘆的JavaScript UI。在文章結(jié)尾處,我們將分享5個(gè)關(guān)于如何使用async / awai...
摘要:最受歡迎的引擎是,在和中使用,用于,以及所使用的。怎么處理每個(gè)引擎都有一個(gè)基本組件,稱(chēng)為調(diào)用棧。也就是說(shuō),如果有其他函數(shù)等待執(zhí)行,函數(shù)是不能離開(kāi)調(diào)用棧的。每個(gè)異步函數(shù)在被送入調(diào)用棧之前必須通過(guò)回調(diào)隊(duì)列。例如方法是在中傳遞的回調(diào)函數(shù)。 ? 翻譯:瘋狂的技術(shù)宅 原文:www.valentinog.com/blog/engine… 從Call Stack,Global Me...
摘要:最受歡迎的引擎是,在和中使用,用于,以及所使用的。單線(xiàn)程的我們說(shuō)是單線(xiàn)程的,因?yàn)橛幸粋€(gè)調(diào)用棧處理我們的函數(shù)。也就是說(shuō),如果有其他函數(shù)等待執(zhí)行,函數(shù)是不能離開(kāi)調(diào)用棧的。每個(gè)異步函數(shù)在被送入調(diào)用棧之前必須通過(guò)回調(diào)隊(duì)列。 翻譯:瘋狂的技術(shù)宅原文:https://www.valentinog.com/bl... 本文首發(fā)微信公眾號(hào):前端先鋒歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 sh...
showImg(https://segmentfault.com/img/bVbjYU7?w=2000&h=1333); 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你! JavsScript 是一門(mén)單線(xiàn)程的編程語(yǔ)言,這就意味著一個(gè)時(shí)間里只能處理一件事,也就是說(shuō) JavaScript 引擎一次只能在一個(gè)線(xiàn)程里處理一條語(yǔ)句。 雖然單線(xiàn)程簡(jiǎn)化了編程代碼,因?yàn)槟悴槐靥珦?dān)心并發(fā)引出的問(wèn)...
閱讀 1416·2021-09-24 10:26
閱讀 1712·2019-08-30 14:14
閱讀 2130·2019-08-29 16:54
閱讀 387·2019-08-29 14:09
閱讀 1503·2019-08-29 12:55
閱讀 961·2019-08-28 18:13
閱讀 1606·2019-08-26 13:39
閱讀 2599·2019-08-26 11:43