Async函数是Brian Terlson提出的ECMAScript提案,目前处于stage 3(candidate 候选)阶段。

| 译者注:ECMAScript提案分三个阶段:草图(Sketch) -> 提案(Proposal) -> 规范(Standard),所以Async很大的希望能成为规范.

在开始解释async函数之前,我想先讲一下如何通过组合Promisesgenerators看起来同步的代码来控制异步操作。

通过 Promises 和 generators 写异步代码

在众多的能用于异步的函数中,Promises,作为ES6的一部分,变得越来越受欢迎。一个例子就是客户端的fetch API,用来发送请求获取数据从而替代XMLHttpRequest。使用fetch看起来像下面这样:

function fetchJson(url) {
return fetch(url)
.then(request => request.text())
.then(text => {
return JSON.parse(text);
})
.catch(error => {
console.log(`ERROR: ${error.stack}`);
});
}
fetchJson('http://example.com/some_file.json').then(obj => console.log(obj));

co库通过使用Promisesgenerators能让代码看起来更同步,上面的例子用co来写就是下面这样子:

const fetchJson = co.wrap(function* (url) {
try {
let request = yield fetch(url);
let text = yield request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
});
fetchJson('http://example.com/some_file.json').then(obj => console.log(obj));

每一次回调(一个generator函数)都会传递一个Promises给到co,然后回调进入暂停状态。一旦Promise执行完毕,co就会触发回调:如果Promise返回fulfilled(成功)yield返回成功状态的值,如果返回rejected(失败)yield就会抛出失败的错误。另外,co会将返回的回调包装成一个Promise(跟then()的用途一样)。

Async 函数

上面的例子用Async函数的基本用法实现如下:

async function fetchJson(url) {
try {
let request = await fetch(url);
let text = await request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
}
fetchJson('http://example.com/some_file.json').then(obj => console.log(obj));

在实现上,async函数更像generators,但是不会转换成generatos函数.

Internally, async functions work much like generators, but they are not translated to generator functions.

Async 函数其他的一些用法

现在存在如下的async函数的变体:

  • Async 函数声明: async function foo() {}
  • Async 函数表达式: const foo = async function() {}
  • Async 方法定义: let obj = { async foo() {} }
  • Async 箭头函数:const foo = async () => {};

深入阅读

Async Functions(Brian Terlson)
Simplifying asynchronous computations via generators(“Exploring ES6”的章节)