1、定義javascript
Async函數是Generator函數的語法糖,但相較來講比Generator函數更強大一些。主要用於1解決一次異步調用異步函數的問題,即當第一個異步調用結束後,再調用第二個異步函數;等第二個調用完成後再調用第三個的這種狀況。在以往的寫法裏,須要進行回掉函數多層嵌套才能實現,但這種寫法會致使多層回調函數嵌套,既不方便維護,也不方便解決。而新的寫法能夠解決以上的這些問題,將其變成相似同步函數同樣的寫法,從而可以極大的減輕代碼的複雜度。java
2、函數示例數組
使用Generator函數實現依次讀取兩個文件,代碼以下:異步
寫成async函數,就應該是下面這樣: async
一比較就會發現,async函數就是將Generator函數的星號(*)替換成async,將yield替換成await而已。函數
3、Async函數的優勢spa
經過比較Async函數和Generator函數的區別,能夠明顯發現,前者對後者的改進,體如今如下三點:code
(1)內置執行器。Generator函數的執行必須依靠執行器,因此纔有了co函數,而async函數自帶執行器。也就是說,async函數的執行,與普通函數如出一轍,只要一行:var result = asyncReadFile();regexp
(2)更好的語義。async和await,比起星號和yield,語義更清楚了。async表示函數裏有異步操做,await表示緊跟在後面的表達式須要等待結果。對象
(3)更廣的適用性。co函數庫約定,yield命令後面只能是Thunk函數或Promise對象,而async函數的await命令後面,能夠跟Promise對象和原始類型的值(數值,字符串和布爾值,但這時等同於同步操做)。
4、Async函數的幾種寫法
這裏的寫法不是函數內的寫法,而是函數自己的寫法:
①函數聲明(聲明式):async在function前
async function foo() { // some code... }
②函數表達式(賦值式):async在function前
let foo = async function () { // some code... }
③對象屬性(屬性式):async在function前
let foo = { bar: async function () { // some code... } }
④對象屬性簡寫:async在函數名前
let foo = { async bar () { // some code... } }
⑤箭頭函數:
let foo = async () => { // some code... }
⑥Class寫法:記得先new一個實例才能用
class Foo { async bar() { // some code... } }
5、Async函數的實現
async函數的實現,就是將Generator函數和自動執行器包裝在一個函數裏。
全部的async函數均可以寫成上面的第二種形式,其中的spawn函數就是自動執行器。下面是spawn函數的實現,基本就是前文自動執行器的翻版。
6、Async函數的用法
同Generator函數同樣,async函數返回一個Promise對象,能夠使用then方法添加回調函數。當函數執行的時候,一旦遇到await就會先返回,等到觸發的異步操做完成,再接着執行函數體內後面的語句。下面是一個例子:
上面代碼是一個獲取報價的函數,函數前面的async關鍵字,代表該函數內部有異步操做,調用該函數時,會當即返回一個Promise函數。
7、補充說明
一、隱式轉換:當await後面跟的不是Promise對象,而是基本類型時,該值會被await經過Promise.resolve
隱式轉換。事實上,能夠被轉換的包括例如Boolean、String、Number、對象、數組等,甚至能夠支持自定義類型。
二、await函數的限制:await所在的位置只能是async函數的直接所在位置,而不能是async函數外,或者是async函數內部的函數
三、返回值的狀態變化:async函數的返回值,是一個Promise對象,即有pending、resolved、rejected三種狀態,當函數執行完畢的時候。pending狀態變化。