這篇文章動機是為了解釋這個問題
往下閱讀之前你需要知道,promise的resolve回調函數會被放在job queue中等待主任務執行完畢后等待執行(這也是文章提到的問題的解答)??梢詤⒖歼@篇文章
代碼一new Promise((resolve, reject) => { resolve(); //將resolved回調函數(then的第一個參數)添加到queue隊列 }).then(() => { console.log("promise1 resolved"); }); new Promise((resolve, reject) => { resolve(); //將resolved回調函數(then的第一個參數)添加到queue隊列 }).then(() => { console.log("promise3 resoved"); }); console.log("main"); //result: //main //promise1 resolved //promise3 resoved
這個結果很好理解,兩個resolve()函數將兩個回調函數依次添加到job queue隊列,主任務隊列執行完后,依次執行job queue中的任務。
代碼二在看代碼前首先要理解promise then函數的返回值也是一個promise,而返回的promise的狀態(pending,resolved,reject)在不同情況下會是不同的值,具體請參考MDN上的解釋。為方便理解,請大家記住下面這段代碼中的then函數的返回值均是處于resolved狀態的promise。并請牢記一個promise如果是resolved狀態則它會將其then回調函數作為一個任務添加到job queue。為方便解釋,我會在代碼中將每個then函數標記為一個任務,希望大家能對照著看。OK,讓我們來看代碼
new Promise((resolve, reject) => { resolve(); //resolve_1 }).then(() => { // then_task_1 console.log("promise1 resolved"); }).then(() => { // then_task_2 console.log("promise2 resolved"); }).then(() => { // then_task_3 console.log("promise3 resolved"); }); new Promise((resolve, reject) => { resolve(); //resolve_2 }).then(() => { // then_task_x console.log("promisex resolved"); }).then(() => { // then_task_y console.log("promisey resolved"); }).then(() => { // then_task_z console.log("promisez resolved"); }); console.log("main"); //result: //main //promise1 resolved //promisex resolved //promise2 resolved //promisey resolved //promise3 resolved //promisez resolved
1,首先resolve_1將then_task_1添加到job queue,然后resolve2將then_task_x添加到job queue。然后執行到console.log("main")。
主任務隊列中的任務執行完成,主任務隊列空(是的,這時job queue中只有then_task_1和then_task_x)。
2,開始執行job queue中的任務:執行then_task_1,打印promise1,這時返一個resolved promise,這個promise的then是then_task_2,js將then_task_2添加到then_task_x后;執行then_task_x,打印promisx,同理將then_task_y添加到then_task_2后。依次類推,我們就看到了代碼結果這樣的打印順序。
new Promise((resolve, reject) => { resolve(Promise.resolve().then(() => { //then_task_innner console.log("inner promise resolved") })); //外層resolve對應then_task1,內層resolve對應then_task_inner }).then(() => { //then_task_1 console.log("promise1 resolved"); }); new Promise((resolve, reject) => { resolve(); //resolve2 }).then(() => { //then_task_2 console.log("promise2 resolved"); }); console.log("main"); //result: //main //inner promise resolved //promise2 resolved //promise1 resolved
這段代碼執行到第一個resolve時發現其參數是一個resolved promise的then回調函數,這個參數是無法立即計算出值來的(因為這個then_task_innner被添加到job queue不會被立即執行)。所以這個resolve函數不會被立即執行。所以到這里then_task_innner被添加到job queue了,但是then_task_1并沒有,因為其對應的promise還處于pending狀態,沒有被resolve。然后執行到resolve2,將then_task_2添加到job queue。然后執行console.log("main"),主任務隊列完成。這時job queue中有then_task_inner和then_task_2。當執行完then_task_inner后,第一個resolve()會被添加到job queue,這時job queue中只有resolve()這個任務,這個resolve被執行。其對應的promise變為resolved狀態,對應的then_task_1被添加到job queue中,然后被執行。因此我們看到屏幕上的打印結果是這樣的。
代碼四有了代碼三的鋪墊,我們現在來看看下面這段代碼。
new Promise((resolve, reject) => { resolve(Promise.resolve()); //為方便解釋,我們將外層的resolve叫做 outer_resolve;內層的resolve叫做inner_resolve }).then(() => { //promise1_task console.log("promise1 resolved"); }); new Promise((resolve, reject) => { resolve(); //resolve2 對應 promise2_task }).then(() => { //promise2_task console.log("promise2 resolved"); }).then(() => { //promise3_task console.log("promise3 resolved"); }); console.log("main"); //result: //main //promise2 resolved //promise3 resolved //promise1 resolved
放這段代碼是為了過渡,方便解釋下面的問題。
這段代碼對比代碼三inner_resolve沒有了.then();不過并不是沒有了,我們可以理解為inner_resolve對應的promise的then函數是null。
程序首先運行到第一個resolve,發現無法立即獲得參數值,對應的promise無法改變狀態,任然是pendding,所以對應的promise1_task不會被添加到job queue。然而inner_resolve被執行了,其對應的then函數(null)被添加到job queue。接下來第二個resolve被執行,對應的promise2_task被添加到job queue。之后主任務執行完成,開始執行job queue中的任務。對一個任務是null,執行完后因為第一個resolve的參數有了,所以這個resolve函數被添加到job queue中;接下來是執行promise2_task,打印promise2 并將promise3_task添加到job queue。然后執行第一個resolve函數,其對應的promise1_task被添加到job queue。接下來是執行promise3_task,然后promise1_task。
如果我們將resolve(Promise.resolve())換成resolve()。就會看到打印結果順序是promise1,promise2,promise3。
new Promise((resolve, reject) => { console.log("async1 start"); console.log("async2"); resolve(Promise.resolve()); //這里的Promise.resolve會添加一個null任務到job queue,外層resolve對應async1_end_task }).then(() => { //async1_end_task console.log("async1 end"); }); new Promise(function(resolve) { console.log("promise1"); resolve(); //對應promise2_task }).then(function() { //promise2_task console.log("promise2"); }).then(function() { //promise3_task console.log("promise3"); }).then(function() { //promise4_task console.log("promise4"); }); //result: //async1 start //async2 //promise1 //promise2 //promise3 //async1 end //promise4
這里我們對async1 start,async2,promise1的打印順序不解釋,這時在主任務中執行的,按主任務執行順序打印。
romise2,promise3,async1 end,promise4的打印順序解釋同代碼四
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99058.html
摘要:如果你要問他和誰當進去的快,要從下面兩個方面考慮結束時。至于什么,查了很多的資料,了解到一個瀏覽器環境只能有一個事件循環,而一個事件循環可以有多個任務隊列。 ====據說這是今日頭條去年的一道筆試題,主要考察的是setTimeout async promise執行順序 ~先雙手奉上這道題目~ async function async1() { consol...
摘要:想必面試題刷的多的同學對下面這道題目不陌生,能夠立即回答出輸出個,可是你真的懂為什么嗎為什么是輸出為什么是輸出個這兩個問題在我腦邊縈繞。同步任務都好理解,一個執行完執行下一個。本文只是我對這道面試題的一點思考,有誤的地方望批評指正。 想必面試題刷的多的同學對下面這道題目不陌生,能夠立即回答出輸出10個10,可是你真的懂為什么嗎?為什么是輸出10?為什么是輸出10個10?這兩個問題在我腦...
摘要:問題是處理完了,卻也引發了自己的一些思考處理的異步操作,都有一些什么方法呢一回調函數傳說中的就是來自回調函數。而回調函數也是最基礎最常用的處理異步操作的辦法。 引言 js的異步操作,已經是一個老生常談的話題,關于這個話題的文章隨便google一下都可以看到一大堆。那么為什么我還要寫這篇東西呢?在最近的工作中,為了編寫一套相對比較復雜的插件,需要處理各種各樣的異步操作。但是為了體積和兼容...
摘要:進一步最終定位發現如果為的時候,效率驟降,如果為合法的字符串的時候,效率是正常值。每次執行該子句都會發生這種情況,將捕獲的異常對象分配給一個變量。盡可能將它們與其他代碼隔離,以免影響其性能。關鍵代碼拆解成如下圖所示(無關部分已省略):起初我認為可能是這個 getRowDataItemNumberFormat 函數里面某些方法執行太慢,從 formatData.replace 到 unesca...
摘要:好吧,本文的主題可能還深入剖析的深復制前端掘金一年前我曾寫過一篇中的一種深復制實現,當時寫這篇文章的時候還比較稚嫩,有很多地方沒有考慮仔細。 翻譯 | 深入理解 CSS 時序函數 - 前端 - 掘金作者:Nicolas(滬江前端開發工程師) 本文原創,轉載請注明作者及出處。 各位,趕緊綁住自己并緊緊抓牢了,因為當你掌握了特別有趣但又復雜的CSS時序函數之后,你將會真正體驗到豎起頭發般的...
閱讀 3626·2021-11-24 09:39
閱讀 2563·2021-11-15 11:37
閱讀 2220·2021-11-11 16:55
閱讀 5221·2021-10-14 09:43
閱讀 3714·2021-10-08 10:05
閱讀 3016·2021-09-13 10:26
閱讀 2334·2021-09-08 09:35
閱讀 3546·2019-08-30 15:55