写在前面的话
在前端面试中,经常会问到ES6属性的问题
而Async是常考题,里面还有一些演变
今天先分享实现原理~
(一)async 函数是什么?
一句话,它就是 Generator 函数的语法糖。
特点
比Generator的改进
1)内置执行器;
2)更好的语义;
3)更广的适用性;
4)返回值是 Promise。
async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
1、形式Generator函数和执行函数
async function fn(args) {
// ...
}
等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
所有的async函数都可以写成上面的第二种形式,其中的spawn函数就是自动执行器。
下面给出spawn函数的实现,基本就是前文自动执行器的翻版。
2、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); });
});
}
3、并发读取远程URL
这个是常考题(划重点),如何并发发出远程请求;
async function logInOrder(urls) {
// 并发读取远程URL
const textPromises = urls.map(async url => {
const response = await fetch(url);
return response.text();
});
// 按次序输出
for (const textPromise of textPromises) {
console.log(await textPromise);
}
}
上面代码中,虽然map方法的参数是async函数,但它是并发执行的,因为只有async函数内部是继发执行,外部不受影响。后面的for..of循环内部使用了await,因此实现了按顺序输出。
参考链接
https://es6.ruanyifeng.com/#docs/async