Promise / fetch / Async-Await
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Spring 2019 。 Ric Huang
Synchronous or Asynchronous?
- 大部分的程式語言都是 synchronous (同步) 的在執行,也就是說,在同一個執行緒裡面的指令是依序的被執行,在前面一個指令執行結束之前,下一個指令是被 block 住的,必須等到前一個指令完成之後,下一個指令才會被執行。
- 例如,在 C/C++ 的程式裡當它在忙著做運算或 I/O 的時候,這時候輸入任何東西它是不理你的
Synchronous or Asynchronous?
- 但在許多的應用,尤其像是在網路的時代,如果一個網頁開啟的時候需要載入一些圖片、影片,你會期待網頁還是會先 show 出來,而只有部分圖片/影片的地方會 load 一下才出來。你不會希望看到的頁面是一片慘白,而必須等到所有圖片、影片都 load 好之後,頁面再 show 出來
Asynchronous Methods/Functions
- 我們需要非同步(asynchronous)的執行程序,讓一些較花時間的指令被呼叫時,可以以 non-blocking 的方式執行,也就是說讓程式可以當下就把執行的控制權要回來(以繼續執行下一個指令),並且 branch 出另外的執行緒來執行這個較花時間的指令,而且雙方約定好一個通知的方式 (e.g. callback function),讓對方完成的時候(不管是成功或是失敗),本來的程式都會立即知道
- 但 "polling" 通常不會是解決非同步程序的選項
概念上像這樣…
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
所以,
JavaScript 是同步還是非同步?
Try this…
// Click when start executing.
// See how the message is printed.
=> JavaScript executes synchronously.
Small tip: 善用 function hoist
有沒有看起來不一樣?
Recall: Callback Functions
- 定義一個 callback function f(), 並且作為參數傳入 g(), 讓我們的程式在執行到 g() 的時候,可以不會因為 g() 的執行時間太久而停下來
Callback Hell
- This kind of callback mechanism is nortorious for the potential "callback hell" situation
- A requests B; while waiting for B, do something
- B requests C; while waiting for C, do something
- Process C's result. Determine success or fail.
- Process B's result. Determine success or fail.
像這樣…
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
To prevent "callback hell" (ref)
-
Keep your code shallow
-
Modularize your code
-
Handle every single error
- This example uses browser-request to make an AJAX request to a server. However, this style may goes into deep callback hell.
1. Keep your code shallow
- To fix it, first name the functions and take advantage of function hoisting to keep the code shallow.
2. Modularize your code
- Secondly, create JavaScript modules — by re-organizing functions into smaller files.
- The above example can be simplified as below when the callback functions are defined in another files.
// “formuploader.js” is where the modules are defined.
3. Handle every single error
-
Note: When dealing with callbacks, you are by definition dealing with tasks that get dispatched, go off and do something in the background, and then complete successfully or abort due to failure.
-
What happens if any of them encounters errors? What happens if you don’t handle the error and continue executing the callback functions?
// Important: Apply the Node.js style where the first argument to the callback is always reserved for an error.
Introducing Promise
-
Promise 物件:定義好一個 asynchronous function 執行之後成功或是失敗的狀態處理
-
使用情境:將 Promise 物件的 .then(), .catch() 加入此 asynchronous function 應該要被呼叫的地方
-
Note: ES6 已經把 promise.js 納入標準
- 想像一下你是個孩子,你媽承諾(Promise)你下個禮拜會送你一隻新手機(some async event)。
- 現在你並不知道下個禮拜你會不會拿到手機。你媽可能真的買了新手機給你,或者因為你惹她不開心而取消了這個承諾 (resolved, or error)
- 為了把這段人生中小小的事件定義好(所以你可以繼續專心的生活),你將問了媽媽以後會發生的各種情況寫成一個 JavaScript function:
ref: https://andyyou.github.io/2017/06/27/js-promise/
- 基本上一個像是 willIGetNewPhone() 的非同步事件會有三種狀態:
- Pending: 未發生、等待的狀態。到下週前,你還不知道這件事會怎樣。
- Resolved 完成/履行承諾。你媽真的買了手機給你。
- Rejected 拒絕承諾。沒收到手機,因為你惹她不開心而取消了這個承諾。
- 我們將把 willIGetNewPhone() 改宣告一個 Promise 物件,來定義上面三種狀態。
- 定義 Promise 物件的語法:
- new Promise(function (resolve, reject) { … });
- 如果一個 Promise 執行成功要在內部 function 呼叫 resolve (成功結果),如果結果是失敗則呼叫 reject (失敗結果)。
- 一個 Promise 物件表達的是一件非同步的操作最終的結果,可以是成功或失敗。
- 用 Promise 定義好 willIGetNewPhone() 之後,我們就可以來改寫 askMom() —
- 在 .then 中使用 function(fullfilled){},而這個 fullfilled 就是從 Promise 的 resolve(成功結果) 傳來的結果 (phone)
- 在 .catch 中我們使用了 function(error) {}。而這個 error 就是從 Promise 的 reject(失敗結果) 傳來的 (reason)
Putting Things Together
- 把 asynchronous function 包成 Promise 物件,用 .then() 與 .catch() 來處理成功與失敗的結果。
Chain of Promises
- 假設有一連串的 asynchronous functions 要執行,可以把他們的 Promise 串聯起來 —
- 其中 doSomething(), doSomethingElse(), doThirdThing() 就是用 Promise 包起來的三個 asynchronous functions
.catch() 後面還是可以接東西
Promise.all()
- Output: Array [ "one", "two" ]
Promise.race()
Promise 好好學,寫 js 沒煩惱。
一個很有用的 Promise — fetch() (ref)
- 有聽過/用過 XMLHttpRequest() 嗎?
- 在 IE7 (2006) 年就有的 API
- 命名有些問題
- API 太過低階
用 fetch() 取代 XMLHttpRequest() —> 回傳 Promise()
- 常用的 res.text() res.json() 都是回傳Promise()
用 fetch() 送 POST
From Promise to Async/Await

- 雖然 ES7 原生支援 async/await, 但每個瀏覽器的支援程度不同,使用前還是要先查一下,否則就要用 Babel.

Promise vs. Async/Await
Promise vs. Async/Await
- Async/Await 的目的在讓 Promise 概念的使用更直覺
- 在 top-level function 前面加個 async
- 用 await 把原先非同步結束後才要在 .then() 執行的程式碼直接隔開,平行的放到下面
- 基本上 async 匡了一個 top-level async 的區域,然後裡面透過 await 變成是 synchronous
Promise vs. Async/Await (ref)


-
Await sequentially

-
Await parallelly

- Nested Await

關於期中 Project (ref)

General Rules
- 題目自訂,一個人一組, 佔學期成績 20%
- Requirements
- Client-side programs in React.js
- Server-side programs in Node.js
- Recommended
- Database to store persistent data
- Use "Promise" or "Async/Await" to ensure asynchronous non-blocking communications
- Deadline: 9pm, Tuesday, 05/21
關於 Github Repo
- 建立一個 public 的 repo (平行於 WebProg2019),命名為:midterm_<yourAppName>
- 請確認可以使用 "npm install" 安裝你的 app, 並且可以使用 "npm start" 執行你的 app
- 如有其他的 scripts 或者是執行時的注意事項, 請在 README.md 中描述清楚
- Project 的目錄與檔案命名名稱不限,但請盡量 follow 上課所講的 conventions (e.g. public, src, containers, components)
- Optional: Deploy 到 cloud 並提供固定網址以利他人操作測試
關於使用他人的框架與模組
- 歡迎使用 React/Node family 相關的 framework (e.g. Next.js),現代化的 web programming 不鼓勵土法煉鋼,多多利用別人開發好的套件/工具,才能達到事半功倍的效果
- 但為了收斂大家的學習,也確保大家有把我們教的 React/Node 真正的趁這個 project 好好複習一下,所以請不要使用別的框架 (e.g. Angular.js, PhP)
- 也歡迎參考別人的 open source 專案,在他的上面去開發你的應用
- 請在 Project 的根目錄編輯一份 README.md,以利助教快速了解你的 project 內容
- 內容應至少包含:
- 題目名稱
- 一句話描述這個 project 在做什麼
- (Optional) Deployed 連結
- 使用/操作方式
- 其他說明
- 使用與參考之框架/模組/原始碼
- 我的貢獻
- 心得
繳交注意事項
- 請在 deadline 以前將 repo 連結 PO 至 FB 社團 (link),發文時請將 README.md 的內容複製貼至 PO 文
- PO 文至 FB 社團即算完成繳交,但請勿在未完成之前 PO 文,以免助教下載到屍體版本
- 評分標準:題目深度(30%)、完成度(40%)、Coding 品質(20%)、是否符合規定(10%)
That's it!!
Enjoy hacking the project!!