成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

js 事件循環(huán)中的job queue和message queue

songze / 3323人閱讀

摘要:等到主任務隊列執(zhí)行完成時此時已打印,執(zhí)行存在隊列中的函數(shù),任務隊列中引入了任務隊列來執(zhí)行的回調(diào)函數(shù)。在這個的回調(diào)函數(shù)中使用創(chuàng)建一個的任務,同時在中調(diào)用函數(shù)創(chuàng)建一個任務。

本文討論的事件循環(huán)均是基于瀏覽器環(huán)境上的,類似nodejs環(huán)境下的事件循環(huán)與此并不相同。

讀者首先要對js單線程事件循環(huán)機制以及Promise有基本理解;如果這兩個概念不是很清楚,建議先閱讀下面兩篇文章:

THE JAVASCRIPT EVENT LOOP?;?Promise 對象

本文是基于THE JAVASCRIPT EVENT LOOP?,并對其內(nèi)容的延伸,所以下面提到的概念都按這篇文章的來。首先我會總結(jié)一下?THE JAVASCRIPT EVENT LOOP?。OK,讓我們開始吧。

1,消息隊列(message queue)

? ? ? 我們知道js單線程的實現(xiàn)方式會把異步任務(setTimeout回調(diào)函數(shù),事件監(jiān)聽回調(diào)函數(shù)等)放在一個消息隊列中;當主任務隊列任務為空時會去message queue查詢是否有等待執(zhí)行的任務,如果有則執(zhí)行。

?例1:

var task_in_message_queue = () => {console.log("task in message queue")}
setTimeout(task_in_message_queue,0);
console.log("main task");

//result:
//main task
//task in message queue

setTimeout函數(shù)將task_in_message_queue函數(shù)添加到message queue隊列中。等到主任務隊列執(zhí)行完成時(此時已打印main task),執(zhí)行存在message queue隊列中的task_in_message_queue函數(shù)

2,任務隊列(job queue)

? ? ? ? ES6中引入了任務隊列來執(zhí)行Promise的回調(diào)函數(shù)。同message queue一樣,job queue中的任務也是在主任務隊列為空時才開始執(zhí)行。

例2:

var promise = new Promise((resolve,reject) => {
    resolve("task in job queue");
});
var resolve_callback = (resolve_message) => {console.log(resolve_message)}
promise.then(resolve_callback);
console.log("main task");

//result:
//main task
//task in job queue

/**
這里有一個有趣的現(xiàn)象

在chrome中打印出的結(jié)果是
main task
task in job queue
undefined  //主任務的函數(shù)返回值

在firefox中的結(jié)果是
main task 
undefined  //主任務的函數(shù)返回值
task in job queue

感覺v8的實現(xiàn)是把job queue整合到了主任務隊列尾部
**/

promise.then 將promise?fulfilled狀態(tài)下的回調(diào)函數(shù)resolve_callback添加到job queue中。等到主任務隊列執(zhí)行完成時(此時已打印main task),執(zhí)行存在job queue隊列中的resolve_callback函數(shù)

這里有一點需要注意的是promise構造函數(shù)會在主任務中立即執(zhí)行,例子如下:

var promise = new Promise((resolve,reject) => {
    resolve("task in job queue");
    console.log("the promise construction executed");
});
var resolve_callback = (resolve_message) => {console.log(resolve_message)}
promise.then(resolve_callback);
console.log("main task");


//result:
//the promise construction executed
//main task
//task in job queue
3,任務隊列(job queue)VS 消息隊列(message queue)

? ? ? ?通過上面的例子我們知道主任務隊列優(yōu)先級是最高的,那么job queue和message queue哪個優(yōu)先級更高呢?答案是job queue,js會將job queue中的任務完全執(zhí)行完之后再執(zhí)行message queue中的任務。例子如下:

var message_task = () => {console.log("message task");}
setTimeout(message_task,0);
var promise1 = new Promise((resolve,reject) => {
    resolve("promise 1 resolved");
});
var promise2 = new Promise((resolve,reject) => {
    resolve("promise 2 resolved");
});
var resolve_callback = (resolve_message) => {console.log(resolve_message)}
promise1.then(resolve_callback);
promise2.then(resolve_callback);
console.log("main task");


//result:
//main task
//promise 1 resolved
//promise 2 resolved
//message task

/**
這里chrome和firefox返回undefined的位置同上面的例子一樣,也是不同的。有興趣的話可以試試看一下。
**/
4,每次執(zhí)行message queue中的任務前都會檢查job queue嗎?

? ? ? ? 現(xiàn)在我們知道job queue的優(yōu)先級高于message queue。那么每次執(zhí)行message queue中任務前會檢查job queue嗎?我的意思是如果當前job queue為空,message queue中有多個任務(假設有m_task1和m_task2)。js開始執(zhí)行message queue中的任務,在執(zhí)行完m_task1時插入了一個j_task1在job queue中。那么接下來是先執(zhí)行m_task2呢還是j_task1呢?如果先執(zhí)行了m_task2的話,就說明js一旦開始執(zhí)行message queue中的任務就會將所有message queue中任務執(zhí)行完再檢查其它任務隊列。如果先執(zhí)行j_task1的話,那么說明再執(zhí)行每個message queue中的任務前都會先檢查其它任務隊列,先執(zhí)行優(yōu)先級高的任務隊列中的任務。為此我們用如下代碼來檢驗:

var promise_task = new Promise((resolve,reject) => {
    resolve("j_task1");
});
var resolve_callback = (resolve_message) => {console.log(resolve_message)}
var message_task1 = () => {
    promise_task.then(resolve_callback);
    console.log("m_task1");
}
var message_task2 = () => {console.log("m_task2");}
setTimeout(message_task1,0);
setTimeout(message_task2,0);


//result:
//m_task1
//j_task1
//m_task2

事實證明js在每次執(zhí)行message queue中的任務前都會檢查其它任務隊列(至少會檢查job queue),根據(jù)隊列優(yōu)先級決定先執(zhí)行哪個隊列中的任務。

5,主任務隊列呢?

? ? ? ? 上面我們了解了job queue和message queue中任務的執(zhí)行順序,簡而言之:在每次一個任務結(jié)束時,js都會根據(jù)任務隊列的優(yōu)先級判斷下一個執(zhí)行任務是哪個。如果job queue中有任務則執(zhí)行job queue中的第一個任務,否則執(zhí)行message queue中的第一個任務。那么主任務隊列是不是也一樣呢?(邏輯上應該是一樣的,否則job queue或者message queue中的任務可以遞歸創(chuàng)建新任務,這樣就永遠無法回到主任務隊列了)。

? ? ? ? 即每次選擇執(zhí)行任務前(或者每次任務結(jié)束后),js會根據(jù)主任務隊列,job queue,message queue的優(yōu)先級來挑選將要執(zhí)行下一個任務是哪個。

? ? ? ? 為此我們聲明一個promise和一個message_task函數(shù)。在這個promise的回調(diào)函數(shù)中使用setTimeout創(chuàng)建一個message_task的message queue任務,同時在message_task中調(diào)用promise.then 函數(shù)創(chuàng)建一個job queue 任務。這樣兩個任務會循環(huán)創(chuàng)建并循環(huán)執(zhí)行。運行后我們會在console中看到兩個任務循環(huán)打印,這是我們在console中鍵入alert("stop")命令。如果頁面顯示了alert,console停止了打印就說明主任務隊列的行為方式和job queue,message queue是一樣的。否則的話,在這種情況下我們將永遠無法回到主任務隊列。驗證代碼如下:

var promise_task = new Promise((resolve,reject) => {
    resolve("j_task");
});
var resolve_callback = (resolve_message) => {
    setTimeout(message_task,0);
    console.log(resolve_message);
}
var message_task = () => {
    promise_task.then(resolve_callback);
    console.log("m_task");
}

promise_task.then(resolve_callback);


//result:
//console會循環(huán)打印 j_task 和 m_task
//這是在console中鍵入alert("stop")命令,觀察是否彈出alert框,console中打印是否終止

希望大家自行求證一下,當然驗證完畢后記得刷新頁面,不然可能就崩了。另:最好在chrome下驗證,firefox有些卡頓。

總結(jié)

? ? ? ? js事件循環(huán)規(guī)律可大致總結(jié)為如下:

? ? ? ? 1,js中有三個任務隊列:主任務隊列,job queue,message queue;

? ? ? ? 2,它們的優(yōu)先級是:主任務隊列 > job queue > message queue;

? ? ? ? 3,每當要執(zhí)行下一個任務前(或者一個任務完成后),js會根據(jù)優(yōu)先級詢問各個任務隊列是否為空,一旦遇到非空任務隊列時則取其第一個任務執(zhí)行。

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99027.html

相關文章

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

    摘要:創(chuàng)建全局上下文由表示,并將全局上下文推到棧頂。在了解異步執(zhí)行之前還需要知道一些概念,事件循環(huán)和回調(diào)隊列也稱為任務隊列或消息隊列。會等待事件循環(huán)調(diào)度。事件循環(huán)事件循環(huán)的作用是查看調(diào)用棧并確定調(diào)用棧是否空閑。 簡評:如果你對 JavaScript 異步的原理感興趣,這里有一篇不錯的介紹。 JavaScript 同步代碼是如果工作的 在介紹 JavaScript 異步執(zhí)行之前先來了解一下, ...

    tolerious 評論0 收藏0
  • 淺析 JS 事件循環(huán)之 Microtask Macrotask

    摘要:常見應用則是為了完成一些更新應用程序狀態(tài)的較小的任務,如處理的回調(diào)和的修改,以便讓這些任務在瀏覽器重新渲染之前執(zhí)行。常見應用執(zhí)行順序的實現(xiàn)需要至少一個和至少一個。 簡介 我們在上一篇 《淺析 JS 中的EventLoop 事件循環(huán)》 中提到一個 Event Queue,其實在事件循環(huán)中 queue 一共有兩種,還有一種叫 Job Queue 其中 Event Queue 在 HTML...

    sihai 評論0 收藏0
  • 淺析 JS 中的 EventLoop 事件循環(huán)(新手向)

    摘要:同時,如果執(zhí)行的過程中發(fā)現(xiàn)其他函數(shù),繼續(xù)入棧然后執(zhí)行。上面我們討論的其實都是同步代碼,代碼在運行的時候只用調(diào)用棧解釋就可以了。 序 Event Loop 這個概念相信大家或多或少都了解過,但是有一次被一個小伙伴問到它具體的原理的時候,感覺自己只知道個大概印象,于是計劃著寫一篇文章,用輸出倒逼輸入,讓自己重新學習這個概念,同時也能幫助更多的人理解它~ 概念 JavaScript 是一門 ...

    chadLi 評論0 收藏0
  • 剖析Laravel隊列系統(tǒng)--Worker

    摘要:一旦這一切完成,方法會運行在類屬性在命令構造后設置容器解析實例,在中我們設置了將使用的緩存驅(qū)動,我們也根據(jù)命令來決定我們調(diào)用什么方法。作業(yè)只在以上起效在上也無效處理作業(yè)方法調(diào)用觸發(fā)事件觸發(fā)事件。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接https://divinglaravel.com/queue-system...

    CollinPeng 評論0 收藏0
  • Javascript event loop

    摘要:包括了操作例如事件綁定,這類操作。每個結(jié)束后,都會進行也就是檢查是否有在等待執(zhí)行,根據(jù)先進先出,依次執(zhí)行。簡單來說,會檢查是否有需要處理的,如果為空時,則會按照先進先出的順序來處理中的。 眾所周知, javascript是一個單線程語言。單線程也就意味著只有一個stack(調(diào)用棧),一次只能做一件事。那么又是如何實現(xiàn)異步操作?先來了解幾個關鍵的術語。 Call Stack 調(diào)用棧 sh...

    reclay 評論0 收藏0

發(fā)表評論

0條評論

songze

|高級講師

TA的文章

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