1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-26 03:32:20 +00:00

docs(async): async函数的语法

This commit is contained in:
ruanyf 2016-06-07 17:14:39 +08:00
parent a8fb385483
commit 571088b40d

View File

@ -727,9 +727,9 @@ ES7提供了`async`函数,使得异步操作变得更加方便。`async`函数
```javascript
var fs = require('fs');
var readFile = function (fileName){
return new Promise(function (resolve, reject){
fs.readFile(fileName, function(error, data){
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) reject(error);
resolve(data);
});
@ -775,9 +775,42 @@ var result = asyncReadFile();
进一步说,`async`函数完全可以看作多个异步操作包装成的一个Promise对象`await`命令就是内部`then`命令的语法糖。
正常情况下,`await`命令后面是一个Promise对象否则会被转成Promise。
### 语法
下面是一个完整的例子。
`async`函数的语法规则总体上比较简单,难点是错误处理机制。
1`async`函数返回一个Promise对象。
`async`函数内部`return`语句返回的值,会成为`then`方法回调函数的参数。
```javascript
async function f() {
return 'hello world';
}
f().then(v => console.log(v))
// "hello world"
```
上面代码中,函数`f`内部`return`命令返回的值,会被`then`方法回调函数接收到。
`async`函数内部抛出错误会导致返回的Promise对象变为`reject`状态。抛出的错误对象会被`catch`方法回调函数接收到。
```javascript
async function f() {
throw new Error('出错了');
}
f().then(
v => console.log(v),
e => console.log(e)
)
// Error: 出错了
```
2`async`函数返回的Promise对象必须等到内部所有`await`命令的Promise对象执行完才会发生状态改变。也就是说只有`async`函数内部的异步操作执行完,才会执行`then`方法指定的回调函数。
下面是一个例子。
```javascript
async function getTitle(url) {
@ -789,6 +822,92 @@ getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"
```
3正常情况下`await`命令后面是一个Promise对象。如果不是会被转成一个立即`resolve`的Promise对象。
```javascript
async function f() {
return await 123;
}
f().then(v => console.log(v))
// 123
```
上面代码中,`await`命令的参数是数值`123`它被转成Promise对象并立即`resolve`
`await`命令后面的Promise对象如果变为`reject`状态,则`reject`的参数会被`catch`方法的回调函数接收到。
```javascript
async function f() {
await Promise.reject('出错了');
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了
```
注意,上面代码中,`await`语句前面没有`return`,但是`reject`方法的参数依然传入了`catch`方法的回调函数。这里如果在`await`前面加上`return`,效果是一样的。
只要一个`await`语句后面的Promise变为`reject`,那么整个`async`函数都会中断执行。
```javascript
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
```
上面代码中,第二个`await`语句是不会执行的,因为第一个`await`语句状态变成了`reject`
为了避免这个问题,可以将第一个`await`放在`try...catch`结构里面,这样第二个`await`就会执行。
```javascript
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// hello world
```
4如果`await`后面的异步操作出错,那么等同于`async`函数返回的Promise对象被`reject`
```javascript
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// Error出错了
```
上面代码中,`async`函数`f`执行后,`await`后面的Promise对象会抛出一个错误对象导致`catch`方法的回调函数被调用它的参数就是抛出的错误对象。具体的执行机制可以参考后文的“async函数的实现”。
防止出错的方法,也是将其放在`try...catch`代码块之中。
```javascript
async function f() {
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
}
return await('hello world');
}
```
### async函数的实现
async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。