javascript 学习: async await

async/await是在 ECMAScript 2017定义的,而Node 7.6开始正式支持aync/await,现在LTS版本是8.x,以下不做说明都是在此环境。

async

async有三种定义方式。

async function

先看一个定义async function的例子:

function resolveAfter2Seconds() {
    return new Promise(resolve => {
        setTimeout(() => {
        resolve('resolved');
        }, 2000);
    });
}
async function asyncCall() {
    console.log('calling');
    var result = await resolveAfter2Seconds();
    console.log(result);
    // expected output: "resolved"
}
asyncCall();

如上定义了一个名为asyncCall的async function。当async被调用的时候,返回Promise,执行完毕,要么resolve一个值,要么 reject一个错误。之所以添加 await是为了等待Promise的执行结果,然后再只想async函数内剩余的部分,这才会输出'resolved'。

async function expression

有了上面的经验,我们来看表达式的定义方式:

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


var add = async function(x) { // async function expression assigned to a variable
    var a = await resolveAfter2Seconds(20);
    var b = await resolveAfter2Seconds(30);
    return x + a + b;
};

add(10).then(v => {
console.log(v);  // prints 60 after 4 seconds.
});

和 async function类似,这里只不过是把function付给了一个变量。注意最后输出是要延迟4秒,因为使用了 await后是顺序同步执行的。如果按下面的写法,输出则延迟2秒:

var add = async function(x) { // async function expression assigned to a variable
    var a =  resolveAfter2Seconds(20);
    var b =  resolveAfter2Seconds(30);
    return x + await a + await b;
};

AsyncFunction对象

使用AsyncFunction构造函数也可以声明一个async function,不过应该很少会直接这么用。

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); // prints 30 after 4 seconds
});

await

await 是为async而生:只能出现在async函数体内,用于等待 Promise。

Promise

前面出现的Promise是javascript中用于异步编程的一种方案,这里简单的介绍下基本概念。
Promise对象代表一个异步操作的最终状态(成功或失败),以及相应状态下的结果。

var promise1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, 'foo');
});
console.log(promise1);

它的定义:new Promise( /* executor */ function(resolve, reject) { ... } );, executor 会立即执行,resolve和reject函数只会执行其中之一。

const myFirstPromise = new Promise((resolve, reject) => {
// do something asynchronous which eventually calls either:
//
//   resolve(someValue); // fulfilled
// or
//   reject("failure reason"); // rejected
});

简单的说,如果一切顺利就resolve结果,不然就reject一个reason。

结合Promise,和上述async/await,个人理解async/await类似对Promise的语法糖。通过对异步函数的控制,实现顺序执行的控制流。

参考资料

牢记这些基本概念,夯实基础,bug就没有那么容易错过。

async function
await
Promise