async原理、用法全揭秘!
目錄
async函數(shù)是什么 async函數(shù)原理 常見的關(guān)于 async的筆試題
async函數(shù)
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函數(shù) foo 可以寫成 async 函數(shù),就是這樣:
const asyncReadFile = async function () {
const f1 = await readFile('/src/lib');
const f2 = await readFile('/src/utils');
console.log(f1.toString());
console.log(f2.toString());
};
可以發(fā)現(xiàn),async函數(shù)就是將Generator函數(shù)的星號(*)替換成async,將 yield替換成 await,僅此而已。
async函數(shù)是基于 Generator的改進,體現(xiàn)在以下4點
內(nèi)置執(zhí)行器。 Generator函數(shù)的執(zhí)行必須靠執(zhí)行器。所以才有了Thunk函數(shù)和co模塊,而async函數(shù)自帶執(zhí)行器。async函數(shù)的執(zhí)行和普通函數(shù)一樣。
asyncReadFile();
更好的語義。
async和await,比起星號和yield,語義更清楚了。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達式需要等待結(jié)果。更廣的適應(yīng)性。即使
Generator函數(shù)可以借助co模塊自動執(zhí)行,但是co模塊后面只能是Thunk函數(shù)或Promise對象,而async函數(shù)的await命令后面,可以是 Promise對象和原始類型的值(數(shù)值、字符串和布爾值,但這是會自動轉(zhuǎn)成立即resolved的Promise對象)返回值是
Promise。aysnc函數(shù)返回值為Promise,這比Generator函數(shù)的返回值是Iterator對象方便多了。
async函數(shù)完全可以看作多個異步操作,包裝成的一個Promise 對象,而await命令就是內(nèi)部then命令的語法糖。
總是就是
Generator函數(shù)雖然是JS借鑒其他語言,根據(jù)JS本身單線程的特點實現(xiàn)的協(xié)程,但是使用起來會麻煩很多,而async函數(shù)就是為了解決這些重復(fù)的事情而生的。其實 ?async函數(shù)就是將Generaor函數(shù)和自動執(zhí)行器包裝了在了一起,然后潤色了一下。
async函數(shù)的實現(xiàn)原理
就是將Generator函數(shù)和自動執(zhí)行器,包裝在一個函數(shù)里。
async function fn(args) {
// ...
}
function fn(args) {
return spawn(function* () {
// ...
})
}
所有的 async 函數(shù)都可以寫成上面的第二種形式,其中 spawn 函數(shù)就是自動執(zhí)行器。
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); });
});
}
常見的關(guān)于async的筆試題
實現(xiàn)一個 sleep實現(xiàn)一個紅綠燈:紅燈2秒,黃燈1秒,綠燈3秒 使用 async實現(xiàn)Promise.all()的效果
實現(xiàn)一個 sleep
每隔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();
實現(xiàn)一個紅綠燈
紅燈2秒,黃燈1秒,綠燈3秒
function sleep(duration) {
return new Promise(resolve => {
setTimeout(resolve, duration);
})
}
async function changeColor(color, duration) {
console.log('當(dāng)前顏色', color);
await sleep(duration);
}
async function main() {
await changeColor('紅色', 2000);
await changeColor('黃色', 1000);
await changeColor('綠色', 3000);
}
main();
使用 async 實現(xiàn) Promise.all()的效果
// 寫法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 寫法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let foo = await barPromise;
上面兩種寫法,getFoo 和 getBar 都是同時觸發(fā)的,這樣就會縮短程序的執(zhí)行時間。
上面只是簡單示例,思考一下,寫出完整代碼。
總結(jié)
async 函數(shù)原理就是 Generator函數(shù) 和 自動執(zhí)行器包裝了一下。最后
如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)
歡迎加我微信「qianyu443033099」拉你進技術(shù)群,長期交流學(xué)習(xí)...
關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。

