更优越的异步解决方案——async await
异步操作是JS的永不过时的话题,总是有人提出各种各样的方案去解决它,最初的回调地狱,到Promise,再有generator函数,直到现在的async函数。
基本规则
声明
定义一个async函数和普通函数的方式无异,可以通过函数声明或者函数表达式,使用如下:
// 函数声明
async function name () {
...
}
// 函数表达式
let example = async function() {
...
}
特性
那么async函数和普通函数的区别在哪呢?使用上的关键有两点:
- 调用该函数后会返回一个Promise对象,当该函数内return一个值时,Promise对象的resolve方法将处理这个值。当函数内抛出异常时,reject方法将处理异常。这部分的值传递方式和Promise链的规则相同。
- async函数内可能会有await表达式,await将会等待一个Promise对象。这会使函数暂停执行直到Promise被决议。如果resolve则不必写then直接得到Promise决议值,reject则抛出异常。如果await等待的不是Promise则等同于同步操作。
原理
总的概括,async函数其实没有新的东西,就是基于以前说过的generator函数,自动执行器和Promise的语法糖。
首先将async函数转化为普通的generator函数,其内部的await和yield在语法上完全相同。
async function example (a, b) {
....await...
}
// 转化后
function example (a, b) {
return spawn(function* () {
....yield...
}, this);
}
这个转化由spawn函数实现,这个spawn函数就是一个返回Promise的自动执行器了。
function spawn (genF, self) {
return new Promise(function (resolve, reject) {
var gen = genF.call(self);
step(() => gen.next(undefined));
function step (nextF) {
var next;
try {
next = nextF();
} catch(e) {
// finished with failure, reject the promise
reject(e);
return;
}
if (next.done) {
// finished with success, resolve the promise
resolve(next.value);
return;
}
// not finished, chain off the yielded promise and `step` again
Promise.resolve(next.value).then(
v => step(() => gen.next(v)),
e => step(() => gen.throw(e))
);
}
});
}
-- EOF --
添加在分类「
前端开发
」下,并被添加
「JavaScript」
标签。