# 深入浅出 async

## 基本概念

简单来讲，`async` 就是 `Generator` 函数的语法糖

表面上一比较，就可以发现 `async` 就是将 `Generator` 函数的型号（\*）替换成 `async`，将 yield 替换成 `await`，本质则是，`async` **内置执行器**且**返回值是 `Promise`**

改进体现在以下四点：

### 内置执行器

`Generator` 需要调用 `next` 或者 `co` 模块才可以真正的执行，而 `async` 只需像普通函数一样调用即可

### 更好的语义

`async` 和 `await`，比起星号和 `yield`，语义更清楚。`async` 代表函数里有异步操作，`await` 表示紧跟在后面的表达式需要等待结果

### 更广的适用性

`co` 模块约定，`yield` 后面只能是 `Thunk` 函数或 `Promise` 对象，而 `async` 函数的 `await` 命令后面，可以是 `Promise` 对象和原始类型的值（数值、字符串和布尔值，但这是会自动转成立即 `resolved` 的 `Promise` 对象）

### 返回值是 `Promise`

`async` 函数的返回值是 `Promise` 对象，这比 `Generator` 函数的返回值是 `Iterator` 对象方便多了。你可以用 `then` 方法指定下一步的操作

## &#x20;基本用法

`async` 函数返回一个 `Promise` 对象，可以使用 `then` 方法添加回调函数。当函数执行的时候，一旦遇到 `await` 就会先返回，等到异步操作完成，才会再接着执行函数体内后面的语句

### 栗子

```javascript
function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

async function asyncPrint(value, ms) {
  await timeout(ms)
  console.log(value)
}

asyncPrint('hello world', 5000)
```

上面代码指定 5 秒之后，输出 `hello world`

## 错误处理

若 `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: 出错了
```
