JS 原力覺醒 Day16 - Async / Await:Promise 語法糖

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 執行完畢後才會繼續往下
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×