es7中的async/await

Node.js es7标准中加入了async/await用于处理异步函数。 async标记的函数中方能调用await, await用于等待异步函数的返回值, 而await目标必须是一个promise对象, 因此实际上await就是对promise对象取它的resolve值。

使用babel-node运行es7代码

1
2
npm install -g babel-cli
npm install babel-preset-es2015 babel-preset-stage-2 --save-dev

然后添加.babelrc文件,添加以下内容:

1
2
3
4
5
6
7
{
"presets": [
"es2015",
"stage-2"
],
"plugins": []
}

此时就可以使用babel-node app.js运行es7代码了。

另一种方式

1
npm install babel-core babel-polyfill --save

在程序入口文件 index.js中:

1
2
3
require('babel-core/register')
require('babel-polyfill')
require('./app')

这样一来也可以在app.js或其他文件中编写es7代码了。

传统的Promise生成

【示例代码1】

1
2
3
4
5
6
7
8
9
10
11
function readWithPromise(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}

这段代码就是一返回一个promise对象,它的作用是读取一个文件的内容,因此我们要调用时只需要如下操作:

【示例代码2】

1
2
3
4
5
6
7
8
9
10
11
async function run() {
let data;
try {
data = await readWithPromise("./package.json");
//data = await readWithGenerator("./package.json");
console.log(data.toString());
} catch(e) {
console.error(e);
}
}
run();

以Generator方式

除此之外,还有一种生成promise对象的方法, 那便是generator, 使用这种方法需要引用co这个包, 代码如下:

【示例代码3】

1
2
3
4
5
6
7
8
9
10
11
import co from 'co';
function readWithGenerator(filePath) {
return co(function*(){
let content = yield ((fp) => {
return (callback) => {
fs.readFile(fp, "utf8", callback);
}
})(filePath);
return content;
});
}

【示例代码1】【示例代码3】作用完全一样, 最后它们都返回一个promise对象,因此调用方式也一样(见【示例代码2】).

小结

await 仅仅只是es7加入的默认对promise的一种处理机制而已,它的作用其实类似于generator里面的yieldyield后面加的可以是一个generator函数,也可以是promise对象,甚至可以是一个promise数组等;而await后面接的只能是一个promise对象,但它们都会在此等待结果返回后才会执行之后的代码。