Async 函数是什么?
一句话,它就是 Generator 函数的语法糖。
但是Generator 還是太複雜
async函数:
1 | const asyncReadFile = async function () { |
Async函数对 Generator 函数的改进,以下四点。
(1)内置執行器。
以下代碼调用了asyncReadFile函数,然后它就会执行,输出最后结果。
1 | asyncReadFile(); |
(2)更好的語意。
async表示函数里有異步操作。
async和await,比起星號和yield(也就是Generator函数),語意更清楚了。await命令只能用在async函数之中,如果用在普通函数,就會報錯。
1 | async function () { |
(3)更廣的適用性。
yield命令后面只能是 Thunk 函数或 Promise 对象
而async函数的await命令后面,可以是 Promise 對象和原始类型的值
(数值、字符串和布尔值,但这时等同于同步操作)
1 | async function () { |
(4)返回值是 Promise。
async函数的返回值是 Promise 對象!
这比 Generator 函数的返回值是 Iterator 對象方便多了。
附上:何謂promise對象?
Async 函数有多种使用形式
其實 async 函数的语法规则总体上比较简单
需要了解的是错误處理機制
Promise 对象
前面提到,async函数的返回值是 Promise 對象!
而async 裡面可以寫很多個await,所以可以視為很多個Promise對象集合!
而resolve(success)
會被then接收到!
而reject(error)
會被catch接收到!
1 | async function f() { |
Promise 的狀態一旦改變,就永久保持该狀態,不會再變
1 | const promise = new Promise(function(resolve, reject) { |
Error & then & catch
async函数内部抛出Error
1.会導致返回的 Promise 对象变为reject状态。
2.抛出的错误对象会被then()catch方法回调函数接收到。
3.只要拋出錯誤,Promise狀態改變,會立即中斷所有後面的程式執行!
1 | async function f() { |
同上,我寫的範例程式碼:https://jsbin.com/zikiqod/edit?js,console
(希望大家玩看看,並確切了解上面三點)
(並判斷throw new Error();
和reject();
之下,catch所接收到的差別)
Over the past 24 hours I’ve been reflecting on my life & I’ve realized only one thing. I need a medieval battle axe.
> 一般来说,不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。
建議不要使用
,then(resolve,reject)的方式
1 | f().then( |
請使用
catch()的方式來取得error!
1 | f().then( |
複雜的機制處理
1 | async function f() { |
情況是,當我們有兩個await異步操作,
結果第一支檔案的異步Promise狀態,
已經拋出錯誤給外面的Promise狀態。
這時候..第二支檔案就不會執行!
而錯誤只會抓到f()
當前遇到的reject(error);資訊
所以我们希望即使前一个異步操作失敗,也不要中断后面的異步操作。
可以將第一个await放在try...catch結構里面
這樣不管這個異步操作是否成功,第二个await都会执行。
1 | async function f() { |
另一種簡寫:await後面的 Promise 對象再跟一个catch方法,來除錯
1 | async function f() { |
使用注意點
- 把await命令放在
try...catch
代码块中。
1 | async function chainAnimationsAsync(elem, animations) { |
- 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。這是等待觸發的方式
1 | let foo = await getFoo(); |
這是同時觸發的方式
1 | // 寫法一 |
- await命令只能用在async函数之中,如果用在普通函数,就会报错。
延伸閱讀
這部分深入理解比較,修行在個人
【與其他異步處理方法的比較】
以及【按顺序完成异步操作】
我擷取其中程式碼,我認為可以激盪一下:
經常遇到一组異步操作,需要按照顺序完成。
比如,依次遠程讀取一组 URL,然后按照讀取的顺序输出结果。
async寫法:
1 | async function logInOrder(urls) { |
寫法大大簡化
但是,是符合次序撈取遠程等待撈取資料,再等待次序輸出結果!
要是可以同時撈取資料,仍然是依次序輸出結果?可以大大改善效率!
async寫法:
1 | async function logInOrder(urls) { |
是否感受到async的強大與易讀!
對於 await 背後的操作方式,還是不太了解
我這邊有寫一個【jsbin連結】玩玩看