# async & await

# 一、AsyncFunction

作用:用来创建新的 异步函数 对象,JavaScript 中每个异步函数都是 AsyncFunction 的对象

获取:非全局对象,需要通过以下方式获取:

Object.getPrototypeOf(async function(){}).constructor

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

functionBody
一段字符串形式的 JavaScript 语句,这些语句组成了新函数的定义。

创建异步函数方式:
1、 直接使用AsyncFunction构造函数创建异步函数对象
2、 用 异步函数表达式【async】 定义一个异步函数,然后再调用其来创建 异步函数 对象
性能:后者比前者更高效,因为第二种方式中异步函数是与其他代码一起被解释器解析的,而第一种方式的函数体是单独解析的。

通过 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);');

// 同以下async定义
var a = async function() {
    return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);
}

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

async 用来定义一个返回AsyncFunction对象的异步函数

const a = async () => {};
const b = Object.getPrototypeOf(async function(){}).constructor;
a instanceof b; 
// true [b = ƒ AsyncFunction() { [native code] }]
# 二、参考

AsyncFunction

# await

await操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用.

await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function。

若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。

另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。

# 为什么说async/await是generator的语法糖

将 async/await 使用 generator 进行改写的关键是要使用 promise 来实现一个 generator 自执行器。在babel中,大体的原理也是类似的。

let test = function () {
  // ret 为一个Promise对象,因为ES6语法规定 async 函数的返回值必须是一个 promise 对象
  let ret = _asyncToGenerator(function* () {
      return yield sleep(1000);
    }
  });
  return ret;
}();

// generator 自执行器,类似co,参考generator.md【co实现自动迭代】
function _asyncToGenerator(fn) {
    // ...
}

# async优点

1、内置执行器

Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器

2、更好的语义

比起星号和yield,async/await语义更清晰;async表示函数里有异步操作,而await表示后面的表达式需要等待结果

3、更广的适用性

co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作