async/await 是 Promise 的語法糖,讓非同步程式碼讀起來像同步。底層仍是 Promise,事件循環沒有改變,只是寫法不同。
async/await 的基本概念
async 函式:使用 async 關鍵字宣告,無論函式本身回傳什麼值,呼叫端拿到的一定是 Promise。
await 運算符:等待一個 Promise 決議(resolve 或 reject)。在標準模式下只能用在 async 函式內;ES2022 起,ES 模組的頂層也可以直接使用 await,不需要包一層 async 函式。
與 Promise 的關係
async/await 本質上是 Promise 的語法糖。看個對照例子:
使用 Promise:
1 | function fetchData() { |
使用 async/await:
1 | async function fetchData() { |
.then() 鏈需要追蹤回呼的巢狀結構,async/await 版本按順序往下讀就夠了。
async/await 與事件循環
async/await 讓程式碼看起來像同步,但執行仍是非同步的。遇到 await 時,目前函式暫停、把控制權交回事件循環,其他程式碼可以繼續跑。等 Promise 決議後,函式才從暫停點繼續。Call stack 不會被堵住。
async/await 與 setTimeout
setTimeout 本身不回傳 Promise,所以要先包一層:
1 | function delay(ms) { |
delay 把 setTimeout 包成 Promise,await 才有東西可以等。這也是用 async/await 整合非原生 Promise API 的標準做法。
async/await 的錯誤處理
用 try/catch 就好,不需要在每個 .then() 後面掛 .catch():
1 | async function fetchData() { |
注意 response.ok 這個判斷——fetch 只在網路層失敗時才 reject,HTTP 4xx/5xx 不會自動進 catch,要自己檢查。
常見陷阱
await 串行 vs 並行
逐一 await 互相獨立的請求,等待時間會累加:
1 | // 慢:兩個請求串行,總共等 A + B |
如果 fetchB 不依賴 fetchA 的結果,用 Promise.all 同時發出請求。
async 函式的回傳值
即使函式回傳普通值,呼叫端拿到的仍是 Promise。呼叫時要記得 await,否則你在比較 Promise 物件而不是值:
1 | async function getCount() { |
瀏覽器支援
Chrome 55、Firefox 52、Safari 11 起原生支援,IE 完全不支援。如果專案不需要顧 IE,現在基本上不需要特別轉譯。





