Promise 讓我們有一個可以很方便寫出非同步函式的方法,不過像這樣非同步的程式碼對於我們在閱讀或是 Debug 要判斷執行的先後順序上可能會比較不值觀,今天要來介紹一組讓 Promise 程式碼的可讀性大大提升的語法糖:Async / Await。
- Promise 語法的問題
- Async
- Await
Promise 語法的問題
常常我們在拉 API 的時候會以 Promise 的方式來實作(例如 axios ),而在這個 Promise 裡的 Callback ,如果又想拉取另外一支 API ,就會需要執行另外一個 Promise , 結果就寫出了難以閱讀的程式碼:
let promise = new Promise (( resolve, reject)⇒{
resolve('some value')
})
promise.then((value)⇒{
let promise2 = new Promise((resolve,reject)=>{
resolve('value2')
})
promise2.then((value2)=>{
...
})
})
這樣子的寫法可能少少幾行還沒事,但當專案變大之後,如果充滿了這樣子的程式碼,那肯定讓你眼花撩亂,所以我們需要 async / await 來做簡化。
Async
async
語法必須寫在函式宣告前面,用來告訴 JS 這個函式是一個非同步的函式,就像這樣:
async function asyncFunc() {
return "Hey!";
}
asyncFunc() // will get a resolved promise.
而用 async
語法所宣告的函式,被呼叫時永遠都會回傳一個 Promise,雖然從上述程式碼看不出來,但是 JS 程式碼會幫你用 Promise 然後包起來回傳給你,就像這樣:
function asyncFunc (){
return new Promise((resolve,reject)=>{
resolve("Hey!")
})
}
Await
await
只能使用在 async
函式內部,在這之外的地方使用的話就會報錯。在 async 函式內部,如果還有其他非同步的程式碼,例如在裡面寫 Promise ,我們就可以用 await
,去告訴 JS 引擎要停下來等待這個非同步程式碼執行完畢,並且等到 Promise 被 resolve 之後才會繼續往下執行。
async function asyncFunc() {
let data = await new Promise((resolve,reject)=>{
// do some calculation
resolve('api data')
})
console.log(data) //'api data'
}
有了 await
之後我們就可以寫出非常容易閱讀的程式碼, async
關鍵字也很明確告訴你這個韓式內有非同步的程式碼,而如果沒有 await
我們原本還需要透過 .then 函式才能拿到 Promise 執行完畢 resolve 之後的值。
更棒的是,如果你的函式內本來有不只一個 Promise 想要依序執行,使用 await
就可以讓你的邏輯以很清楚的方式表現:
async function asyncFunc() {
let promise1 = await new Promise((resolve,reject)=>{
// do some calculation
resolve('api data')
})
let promise2 = await new Promise((resolve,reject)=>{
// get res data of promise1 and do some thing
resolve('success!')
})
console.log(promise2) //'success'
}
不過有一個小缺點是因為使用 await
的話,因為 JS 引擎會一直等待 Promise 執行完畢,所以如果過度濫用的話,那就失去非同步的意義了,這點在使用時要多多注意,自己斟酌。
Error Handling
使用 async / await 這個語法糖時,為了讓錯誤處理也變得更簡潔,可以搭配 try / catch 使用:
async function asyncFunc() {
try{
let data = await new Promise((resolve,reject)=>{
// do some calculation
resolve('api data')
})
console.log(data) //'api data'
}catch(e){
console.log('error',e)
}
}
結論
- async / await 只是一個 Promise 的語法糖,讓你可以更方便寫出非同步程式碼
- async 函式一定會回傳一個 Promise
- await 只能在 async 函式內使用
- await 語法會讓 JS 引擎等待 Promise 執行完畢後才會繼續往下