iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
自我挑戰組

菜雞們,讓我們一起征服JS及React吧系列 第 25

React菜雞-Day25:學會JS獨特的用法,讓你的React更優雅~搞懂JS引擎如何安排Promise

  • 分享至 

  • xImage
  •  
tags: 鐵人賽 React javascript nodejs

鐵人賽第25天,前幾天我們學會了PromisePromise-chain,對於異步程式有了基本的了解。今天我們要深入探討使用它的眉角,搞懂它,將更清楚它背後的運作方式。

Promise奇怪的地方

/images/emoticon/emoticon04.gif

  • 先來看以下的程式碼,從輸出的結果你可能會滿臉黑人問好~!?奇怪,明明依序執行下來,怎麼先印出中間的console.log("code finished");
let promise = Promise.resolve();

promise.then(() => console.log("promise done!"));
promise.then(() => console.log("promise done!"));
promise.then(() => console.log("promise done!"));

console.log("code finished"); // <-- !!!

let promise2 = Promise.resolve();
promise2.then(() => console.log("promise2 done!"));
promise2.then(() => console.log("promise2 done!"));
promise2.then(() => console.log("promise2 done!"));
  • 顯示的部分是
code finished  //<-- 怎麼回事!?前面不是有promise在運行了嗎?
promise done!
promise done!
promise done!
promise2 done!
promise2 done!
promise2 done!

管理微任務的 Microtask Queue

/images/emoticon/emoticon33.gif

  • 在ES8裡,ECMA標準針對異步任務進行適當的管理,其利用Microtask Queue來處理這些Promise Jobs
  • 也就是說,JS Engine會先解析程式碼,然後依序執行:
  • 非Promise的script
  • Promise的then/catch/finally異步程式(依時間順序執行)

用setTimeout來改寫一次,你就會懂背後的機制

/images/emoticon/emoticon12.gif

let promise = Promise.resolve();

promise.then(() => setTimeout(()=>console.log("===>5secs promise done!")), 5000); // 5 secs後執行
promise.then(() => console.log("promise done!")); // 立即執行
promise.then(() => console.log("promise done!")); // 立即執行

console.log("code finished"); // <--先執行

let promise2 = Promise.resolve();
promise2.then(() => setTimeout(()=>console.log("===>1secs promise2 done!")), 1000); // 1 sec後執行
promise2.then(() => console.log("promise2 done!")); // 立即執行
promise2.then(() => console.log("promise2 done!")); // 立即執行
  • 印出
code finished
promise done!
promise done!
promise2 done!
promise2 done!
===>5secs promise done!
===>1secs promise2 done!

指定Promise接續著做其他任務

  • 從上圖來看,d一定會比c還要早執行。
  • 那如果我們想讓c執行完之後,接著執行d,該如何進行呢?
  • 這時候,Promise chain登場囉!,你只要在Promise.then(C)後面多加一個.then(d),就可以囉!
let promise = Promise.resolve();

promise.then(() => setTimeout(()=>console.log("===>5secs promise done!")), 5000);

promise
.then(() => console.log("promise done!"))
.then(()=>console.log("code finished")) //<--接續執行


let promise2 = Promise.resolve();
promise2.then(() => setTimeout(()=>console.log("===>1secs promise2 done!")), 1000);
  • 印出
promise done!
code finished
===>5secs promise done!
===>1secs promise2 done!

結論

  • Promise異步在JS裡扮演著很重要的角色,讓我們的前端程式能執行得更有效率,好東西~不學嗎~?
  • 鐵人賽第25天,依舊在忙碌中完成,最後5天了,咱們繼續努力,快到終點囉!加油!!
    /images/emoticon/emoticon62.gif

上一篇
React菜雞-Day24:moment.js 讓你抓住時間的每一刻
下一篇
React菜雞-Day26:學會JS獨特的用法,讓你的React更優雅~ async及await
系列文
菜雞們,讓我們一起征服JS及React吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言