HTTP Networking(4) Asynchronous
同步與非同步
- synchronous: 也就是同步的程式碼,代表程式是按照順序執行,一行執行結束才執行下一行。
舉例來說 下面 console 的程式碼會逐行執行。
1 | console.log("I print first"); |
- asynchronous: 非同步的程式碼,讓我們可以同時執行不同的程式碼,舉例來說:
1 | console.log("I print first"); |
在js裡,當執行一般同步的程式碼時,那沒有問題就一行接一行執行,但當遇到非同步的程式碼時,如 setTimeout、打api時,js會將非同步程式碼放到事件儲列,並接著執行下面的程式碼,等同步的程式碼跑完後就會跑事件儲列裡的程式碼。
好處是,我們不用等待非同步的程式碼執行完才能執行下一步,我們可以同時進行。
為什麼需要非同步
我們會希望盡量保持程式是同步執行的,因為那比較簡單了解。但有時也需要非同步的程式碼,例如當使用者操作更新一個網頁時,瀏覽器需要和伺服器溝通取得新資料,這個 HTTP request 通常會花 100 毫秒左右,如果使用者必須等 100毫秒才能在操作網頁,甚至連滑鼠都不能使用,會是很糟的使用者體驗。
藉由非同步的程式碼,可以讓網頁在等待 HTTP request 的同時,執行其他code,讓使用者體驗更好。
Promise
在 js 中有內建的 Promise物件來處理非同步程式,就和現實世界做一個承諾(promise)一樣,會有兩種結果,要嘛我成功行承諾(resovle),要嘛我沒有履行承諾(reject),程式碼如下:
1 | const promise = new Promise((resolve, reject) => { |
上面程式碼會在1秒後,若成功回傳 resolved! 、失敗回傳rejected! 當我們在等待 promise 結果回傳前,其他程式碼會同時被執行。
如何使用 pormise
pormise 物件有兩個方法:
- .then: 如果promise resolve, .then方法會被執行。
- .catch: 如果promise reject, .catch方法會被執行。
1 | promise.then((message) => { |
await
除了 .then() .catch()
,也可以用 await 。
await 會等待 Promise 被 resolve 後將值回傳。
1 | const message = await promise |
但這不代表整個 js 程式會停止並等待,而只是這段程式會 await 等待。
await 可以讓我們將非同步的程式碼寫得和同步的程式碼一樣,
且 await keyword 只能使用在 async function 中或程式的第一層top level module。
async function
就像 await 被用來取代 .then() 一樣, async function 被用來取代 new Promise
。
當一個 function 前面加上 async 關鍵字時,這個function 會自動回傳一個 promise,這個promise resolve的值,就是function return 出來的值。
以下為 promise 和 async function 的範例:
1 | // promise 範例 |
1 | // async function 範例 |
async function 的優點
比起 .then()
使用 async function 可以讓程式碼更簡單易懂
.then()
寫法
1 | fetchUser.then(function(user){ |
async 寫法
1 | const user = await fetchUser() |