iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
1

一路上感謝各位讀者們的支持和回饋。
本 30 天系列文目前已經將篇幅重新整理、編纂成冊。
《JavaScript 概念三明治》在天瓏書局上架囉!
喜歡這個系列,想閱讀更詳細原理說明的讀者可以參考:
https://www.tenlong.com.tw/products/9789864347575

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 執行完畢後才會繼續往下

上一篇
JS 原力覺醒 Day15 - Macrotask 與 MicroTask
下一篇
JS 原力覺醒 Day17 - this 的四種繫結
系列文
JavaScript 原力覺醒 - 成為絕地武士之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言