在 JavaScript 中处理异步操作的回调 (callback) 通常会导致多嵌套的代码块,俗称回调地狱 (callback hell),这样的代码复杂,可读性,可维护性非常不友好;直达 ES6,Promise 出现,使得我们能够扁平化回调函数,告别回调地狱,写出优雅的代码;但是在实践中发现,Promise 并不完美,如果 Promise 的回调中出现嵌套,依旧会出现回调地狱;而如今,async await 出现了,它提供了一种新的编写异步代码方式,使得异步代码看起来像是同步代码,这正式它的魔力所在。
异步函数
1 2 3 4 5 6 7 8 9 |
// async function statement:async function 声明语句 async function name([param[, param[, ... param]]]) { statements } // async function expression:async function 表达式 async function [name]([param1[, param2[, ..., paramN]]]) { statements } |
如上,可以通过 async function 声明语句或者表达式来定义一个异步函数,返回一个 AsyncFunction
对象,二者的区别在于在于函数名称,async function 表达式可以省略函数名称来创建一个匿名的函数。
调用异步函数时会返回一个 promise 对象
- 当这个异步函数返回一个值时,promise 的 resolve 方法将会处理这个返回值
- 当异步函数抛出异常或者非法值时,promise 的 reject 方法将处理这个异常值
1 2 3 4 5 6 |
async function test () { return 'ok' // throw new Error('error') } test().then(console.log, console.error) |
AsyncFunction
注意,
AsyncFunction
并不是一个全局对象,我们可以这样获得AsyncFunction
1
Object.getPrototypeOf(async function () {}).constructor
AsyncFunction
构造函数用于创建一个新的 async function 对象,在 JavaScript 中,每一个异步函数都是一个 AsyncFunction
1 2 3 4 5 6 7 8 9 |
console.log(async function () {}.constructor) // -> ƒ AsyncFunction() { [native code] } console.log(async function () {}.__proto__) // -> AsyncFunction {Symbol(Symbol.toStringTag): "AsyncFunction", constructor: ƒ} var AsyncFunction = Object.getPrototypeOf(async function () {}).constructor var asyncFun = async function () {} console.log(asyncFun instanceof AsyncFunction) // -> true |
通过 AsyncFunction
构造函数创建异步函数的语法如下:
1 |
new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody) |
把 AsyncFunction
当成函数调用(省略 new
操作符)也可创建异步函数,如下:
1 2 3 4 |
var AsyncFunction = Object.getPrototypeOf(async function () {}).constructor; // var func = new AsyncFunction('a', 'b', 'return a+b') var func = AsyncFunction('a', 'b', 'return a+b') func(1, 2).then(console.log) // -> 3 |