async
的筆試題const fs = require('fs'); const readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error){ return reject(error); } resolve(data); }); }); }; const foo = function* () { const f1 = yield readFile('/src/lib'); const f2 = yield readFile('/src/utils'); console.log(f1.toString()); console.log(f2.toString()); };
把上面代碼的Generator
函數 foo
能夠寫成 async
函數,就是這樣:異步
const asyncReadFile = async function () { const f1 = yield readFile('/src/lib'); const f2 = yield readFile('/src/utils'); console.log(f1.toString()); console.log(f2.toString()); };
能夠發現, async
函數就是將Generator
函數的星號(*
)替換成async
,將 yield
替換成 await
,僅此而已。async
async
函數是基於 Generator
的改進,體如今如下4點函數
1 . 內置執行器。 Generator
函數的執行必須靠執行器。因此纔有了 Thunk
函數和co
模塊,而 async
函數自帶執行器。async
函數的執行和普通函數同樣。ui
asyncReadFile();
2 . 更好的語義。async
和awai
t,比起星號和yield
,語義更清楚了。async
表示函數裏有異步操做,await
表示緊跟在後面的表達式須要等待結果。spa
3 . 更廣的適應性。
即便 Generator
函數能夠藉助co
模塊自動執行,可是co
模塊後面只能是 Thunk
函數或Promise
對象,而async
函數的await
命令後面,能夠是 Promise對象和原始類型的值(數值、字符串和布爾值,但這是會自動轉成當即 resolved
的 Promise對象
)線程
4 . 返回值是 Promise
。
aysnc函數返回值爲 Promise
,這比Generator
函數的返回值是Iterator
對象方便多了。code
async
函數徹底能夠看做多個異步操做,包裝成的一個 Promise
對象,而await命令就是內部then
命令的語法糖。協程
老是就是Generator
函數雖然是JS借鑑其餘語言,根據JS自己單線程的特色實現的協程,可是使用起來會麻煩不少,而async
函數就是爲了解決這麼麻煩而生的。其實async
函數就是將Generaor
函數和自動執行器包裝了在了一塊兒,而後潤色了一下。
就是將Generator函數和自動執行器,包裝在一個函數裏。對象
async function fn(args) { // ... } function fn(args) { return spawn(function* () { // ... }) }
全部的 async
函數均可以寫成上面的第二種形式,其中 spawn 函數就是自動執行器。接口
function spawn(genF) { return new Promise(function(resolve, reject) { const gen = genF(); function step(nextF) { let next; try { next = nextF(); } catch(e) { return reject(e); } if(next.done) { return resolve(next.value); } Promise.resolve(next.value).then(function(v) { step(function() { return gen.next(v); }); }, function(e) { step(function() { return gen.throw(e); }); }); } step(function() { return gen.next(undefined); }); }); }
async
的筆試題sleep
:async
實現 Promise.all()
的效果每隔1秒輸出 1, 2, 3, 4, 5
function sleep(interval) { return new Promise(resolve => { setTimeout(resolve, interval); }) } // 用法 async function one2FiveInAsync() { for (let i = 1; i <= 5; i++) { console.log(i); await sleep(1000); } } one2FiveInAsync();
紅燈2秒,黃燈1秒,綠燈3秒
function sleep(duration) { return new Promise(resolve => { setTimeout(resolve, duration); }) } async function changeColor(color, duration) { console.log('當前顏色', color); await sleep(duration); } async function main() { await changeColor('紅色', 2000); await changeColor('黃色', 1000); await changeColor('綠色', 3000); } main();
// 寫法一 let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 寫法二 let fooPromise = getFoo(); let barPromise = getBar(); let foo = await fooPromise; let foo = await barPromise;
上面兩種寫法,getFoo 和 getBar 都是同時觸發的,這樣就會縮短程序的執行時間。
上面只是簡單示例,思考一下,寫出完成代碼。
async
函數原理就是 Generator
函數 和 自動執行器包裝了一下。Generator
就是能夠暫定執行和在以前停下的位置接着執行。好比發送一個接口請求,發出以後,JS能夠去幹其餘的事兒,接口請求回來以後(數據經過next傳入),會接着繼續執行。可是它不能自動執行,因此須要自動執行器, thunk
函數和co
模塊都是,可是async給咱們封裝得更加完美。