国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

異步 JavaScript - 事件循環(huán)

tolerious / 1466人閱讀

摘要:創(chuàng)建全局上下文由表示,并將全局上下文推到棧頂。在了解異步執(zhí)行之前還需要知道一些概念,事件循環(huán)和回調(diào)隊列也稱為任務(wù)隊列或消息隊列。會等待事件循環(huán)調(diào)度。事件循環(huán)事件循環(huán)的作用是查看調(diào)用棧并確定調(diào)用棧是否空閑。

簡評:如果你對 JavaScript 異步的原理感興趣,這里有一篇不錯的介紹。
JavaScript 同步代碼是如果工作的

在介紹 JavaScript 異步執(zhí)行之前先來了解一下, JavaScript 同步代碼是如何執(zhí)行的。

這里有兩個概念需要了解:

執(zhí)行上下文(Excution Context)

執(zhí)行上下文是一個抽象的概念,用于表示 JavaScript 的運行環(huán)境,任何代碼都會有一個執(zhí)行上下文。

全局代碼運行在全局執(zhí)行上下文,函數(shù)里的代碼運行在函數(shù)執(zhí)行上下文,每一個函數(shù)都有自己的執(zhí)行上下文。

調(diào)用堆棧(Call Stack)

調(diào)用棧是一個具有 LIFO(后進先出)結(jié)構(gòu)的棧,用于儲存代碼執(zhí)行階段所有的執(zhí)行上下文。

因為 JavaScript 是單線程的,所以 JavaScript 只有一個多帶帶的調(diào)用棧。

我們以下面例子介紹同步代碼執(zhí)行過程。

const second = () => {
  console.log("Hello there!");
}
const first = () => {
  console.log("Hi there!");
  second();
  console.log("The End");
}
first();

創(chuàng)建全局上下文(由 main() 表示),并將全局上下文推到棧頂。然后依次將遇到函數(shù)執(zhí)行上下文推到棧頂(如果函數(shù)中執(zhí)行其他他函數(shù),其他函數(shù)依次推到棧頂以此類推)。當函數(shù)執(zhí)行完畢對應(yīng)的執(zhí)行上下文會從調(diào)用棧彈出,程序結(jié)束時全局上下文從調(diào)用棧彈出。

JavaScript 異步代碼是如何執(zhí)行的?

通過上個章節(jié)我們已經(jīng)對調(diào)用棧和 JavaScript 的同步執(zhí)行有了基本的了解,現(xiàn)在來看看 JavaScript 異步執(zhí)行是如何工作的。

什么是阻塞?

由于 JavaScript 是單線程的,如果某個函數(shù)耗費的時間比較長,會阻塞后面的任務(wù)執(zhí)行,這就造成了阻塞。解決阻塞最簡單的方法是函數(shù)直接返回不等待,使用異步回調(diào)來處理返回結(jié)果。

在了解 JavaScript 異步執(zhí)行之前還需要知道一些概念,事件循環(huán)和回調(diào)隊列(也稱為任務(wù)隊列或消息隊列)。

注意:Event Loop 、Web APIs 和 Message Queue 并不是 JavaScript 引擎的一部分,而是瀏覽器運行時環(huán)境和 Nodejs 運行時環(huán)境的一部分。

我們以下面代碼為例,解釋異步代碼是如何執(zhí)行的。

const networkRequest =()=> { 
  setTimeout(()=> { 
    console.log("Async Code"); 
  },2000); 
};
console.log("Hello World");
networkRequest();
console.log("The End");

當上述程序加載到瀏覽器時 console.log(‘Hello World’) 代碼執(zhí)行時會一次在調(diào)用棧推入和彈出。遇到 networkRequest() 將其推入到調(diào)用棧頂。然后繼續(xù)將 networkRequest 內(nèi)的 setTimeout 方法推入棧頂,隨后 setTimeout networkRequest 依次出棧。最后對 console.log(‘The End’) 進行入棧出棧。

當 timer 到期后會將 callback 推入 message queue(消息隊列)中,此時 callback 不會馬上執(zhí)行。會等待事件循環(huán)調(diào)度。

事件循環(huán)

事件循環(huán)的作用是查看調(diào)用棧并確定調(diào)用棧是否空閑。如果調(diào)用棧空閑,even loop 會查看消息隊列是否有待處理的 callback 需要觸發(fā)。例子中的消息隊列只包含一個 callback,當調(diào)用棧為空的時候,even loop 會將 callback 推入調(diào)用棧中觸發(fā) networkRequest 的回調(diào)。

DOM 事件

消息隊列還會包含來自 DOM 的事件回調(diào),比如鼠標和鍵盤事件回調(diào)。例如:

document.querySelector(".btn").addEventListener("click",function callback(event) {
  console.log("Button Clicked");
});

對于 DOM 事件,當具體的事件觸發(fā)會將 callback 推入消息隊列中,等待 even loop 來調(diào)度執(zhí)行。

ES6 job queue/micro-task queue

ES6 新增了 job queue/micro-task queue 概念,在 Promise 中用到。job queue 比 message queue 擁有更高的優(yōu)先級。意味著 job queue 和 message queue 都有任務(wù)時會優(yōu)先執(zhí)行 job queue 中的任務(wù)。例如:

console.log("Script start");

// callback 在 message queue 中
setTimeout(function callback() {
  console.log("setTimeout");
}, 0);

// 任務(wù)在 micro-task queue 中
new Promise((resolve, reject) => {
    resolve("Promise resolved");
  }).then(res => console.log(res))
    .catch(err => console.log(err));
console.log("Script End");

// 輸出:
Script start
Script End
Promise resolved
setTimeout

再來看下一個例子(兩個 setTimeout 和 兩個 Promise):

console.log("Script start");
setTimeout(() => {
  console.log("setTimeout 1");
}, 0);
setTimeout(() => {
  console.log("setTimeout 2");
}, 0);
new Promise((resolve, reject) => {
    resolve("Promise 1 resolved");
  }).then(res => console.log(res))
    .catch(err => console.log(err));
new Promise((resolve, reject) => {
    resolve("Promise 2 resolved");
  }).then(res => console.log(res))
    .catch(err => console.log(err));
console.log("Script End");


//輸出為
Script start
Script End
Promise 1 resolved
Promise 2 resolved
setTimeout 1
setTimeout 2

由此可見 micro-task queue 中的所有任務(wù)都會優(yōu)先于 message queue 中的任務(wù)執(zhí)行。

原文:Understanding Asynchronous JavaScript?—?the Event Loop

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99753.html

相關(guān)文章

  • 總結(jié)javascript基礎(chǔ)概念(二):事件隊列循環(huán)

    摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務(wù)隊列掛在當前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計時不準確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點?有什么解決方...

    zhkai 評論0 收藏0
  • JavaScript單線程事件循環(huán)(Event Loop)那些事

    摘要:概述本篇主要介紹的運行機制單線程事件循環(huán)結(jié)論先在中利用運行至完成和非阻塞完成單線程下異步任務(wù)的處理就是先處理主模塊主線程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機制完成調(diào)度涉及的內(nèi)容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運行機制:單線程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運行至...

    Shisui 評論0 收藏0
  • JavaScript 運行機制詳解(理解同步、異步事件循環(huán))

    摘要:從異步過程的角度看,函數(shù)就是異步過程的發(fā)起函數(shù),事件監(jiān)聽函數(shù)就是異步過程的回調(diào)函數(shù)。事件觸發(fā)時,表示異步任務(wù)完成,會將事件監(jiān)聽器函數(shù)封裝成一條消息放到消息隊列中,等待主線程執(zhí)行。 1.為什么JavaScript是單線程? JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。那么,為什么JavaScript不能有多個線程呢?這樣能提高效率啊。JavaScrip...

    loonggg 評論0 收藏0
  • (轉(zhuǎn))JavaScript:同步、異步事件循環(huán)

    摘要:事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊列中取消息執(zhí)行的過程。事件觸發(fā)時,表示異步任務(wù)完成,會將事件監(jiān)聽器函數(shù)封裝成一條消息放到消息隊列中,等待主線程執(zhí)行。 一. 單線程 我們常說JavaScript是單線程的。 所謂單線程,是指在JS引擎中負責解釋和執(zhí)行JavaScript代碼的線程只有一個。不妨叫它主線程。 但是實際上還存在其他的線程。例如:處理AJAX請求的線程、處理DOM事件的線...

    android_c 評論0 收藏0
  • JavaScript運行機制和事件循環(huán)

    摘要:主線程不斷重復(fù)上面的三步,此過程也就是常說的事件循環(huán)。所以主線程代碼執(zhí)行時間過長,會阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機制任務(wù)隊列的順序機制事件循環(huán)搞懂異步事件輪詢與中的事件循環(huán) 1. 說明 讀過本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問題 首先通過一段代碼來驗證你是否了解代碼輸出順序,如果你不知道輸出...

    Ververica 評論0 收藏0
  • 【筆記】 你不知道的JS讀書筆記——異步

    摘要:異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個回調(diào)再放入事件循環(huán)隊列中。 基礎(chǔ):瀏覽器 -- 多進程,每個tab頁獨立一個瀏覽器渲染進程(瀏覽器內(nèi)核) 每個瀏覽器渲染進程是多線程的,主要包括:GUI渲染線程 JS引擎線程 也稱為JS內(nèi)核,負責處理Javascript腳本程序。(例如V8引擎) JS引擎線程負...

    junnplus 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<