JavaScript(ECMAScript 2017)新增的AsyncFunction对象

 2017年03月24日    1000     声明


AsyncFunction对象于2016年进入ECMAScript提议的stage 4阶段,并会于2017年被纳入语言标准(ECMAScript 2017当前已处于起草阶段),成为ECMAScript的标准内置对象。最新版本的Chrome(55+)、Firefox(52.0+)、Node.js(7.6.0+)已提供了对该对象的支付,本篇简单介绍和使用该对象。

  1. AsyncFunction对象
  2. async function表达式
  3. await表达式

1. AsyncFunction对象

JavaScript中的每个异步函数实际上都是AsyncFunction对象。创建一个AsyncFunction对象可以使用AsyncFunction构造函数,也可以使用async function表达式

AsyncFunction构造函数

new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)

参数

  • arg1, arg2, ... argN:函数参数,字符串形式
  • functionBody:函数声明,函数语句字符串

使用AsyncFunction构造函数创建AsyncFunction实例时需要注意以下两点:

  1. 函数体是字符串形式,这和使用Function构造函数创建普通函数的结构是一样
  2. AsyncFunction并不是全局对象,需要通过以下语句来获取对它的引用:
    var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor

AsyncFunction构造函数的使用

使用AsyncFunction构造函数创建一个异步函数:

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor

var a = new AsyncFunction('a', 
                          'b', 
                          'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');

a(10, 20).then(v => {
  console.log(v); // 4秒后,输出 30
});


异步函数调用时会返回一个promise对象。当其返回的一个值时,promiseresolve方法会处理这个返回值;当异步函数抛出的是异常或者非法值时,promisereject方法会处理这个异常值。

resolvedrejected状态外,promise还可能会处于pending(等待)状态。这时可以在异步函数中使用await表达式await会使异步函数暂停执行并等待promise解析传值后,继续执行异步函数并返回解析值。


2. async function表达式

从前面示例可以看出,AsyncFunction构造函数创建对象时操作比较麻烦,而且执行效率也不高。因此,更推荐使用async function表达式。

使用async function表达式创建AsyncFunction对象的语法结构如下:

async function name([param[, param[, ... param]]]) {
  statements
}

使用示例

使用async function表达式重写前面构造函数创建的异步函数:

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function a(a, b) {
	return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);
}

a(10, 20).then(v => {
  console.log(v); // 4秒后,输出 30
});


3. await表达式

await表达式会在异步函数内部使用,它会暂停异步函数的执行并且等待promise返回resolvedrejected状态值。

当返回resolved状态值时,异步函数会恢复执行并返回resolved 值。如果返回的值不是一个promise,那么它将会被转换成一个resolved后的promise

如果返回promiserejected状态,则await表达式会抛出异常值。

await使用示例

当一个promise被传给await表达式时,它将会等待promise处理完成并返回resolved值:

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}
f1();

即使返回值不是promise,也会被转换为一个resolved状态的promise

async function f2() {
  var y = await 20;
  console.log(y); // 20
}
f2();

如果返回的是rejected状态的promise,那么异常会被抛出:

async function f3() {
  try {
    var z = await Promise.reject(30);
  } catch (e) {
    console.log(e); // 30
  }
}
f3();