Skip to main content

Async 和 Await

一、Async

Async 自动将常规函数转换成 Promise,返回一个 Promise 对象。

示例:

// 普通函数
function fn() {
return 23
}
console.log(fn()); // 23

// 使用 async
async function fn() {
return 23
}
console.log(fn()) // Promise {<fulfilled>: 23}
console.log(fn() instanceof Promise) // true

async 函数显示返回的结果如果不是 Promise,会自动包装成 Promise 对象,也就是说上面的代码等同于:

async function fn() {
return Promise.resolve(23)
}

二、Await

Await 是个运算符,可用于等待 Promise 对象 resolve 的值或任意表达式的结果,需要在 async 函数内部使用。

如果 Await 等到的是一个 Promise 对象,那么会阻塞后面的代码,等 Promise 对象 resolve 并将得到 resolve 的值作为 Await 表达式的运算结果。

示例:

// 未使用 await
async function fn() {
let promise = new Promise((resolve) => {
setTimeout(() => resolve(123), 1000)
})
console.log(promise.then(val => console.log(val)))
console.log(456)
}
fn()
// 依次输出:
// 456
// 123


// 使用 await
async function fn() {
let promise = new Promise((resolve) => {
setTimeout(() => resolve(123), 1000)
})
console.log(await promise)
console.log(456)
}
fn()
// 依次输出:
// 123
// 456

await 的字面意思为“等待”,它等什么呢?等的是 Promise 的返回结果,上面这段代码由 async 开启一个 Promise 对象,函数内部嵌套了一个 Promise 操作,这个操作需要等待 1 秒才返回“123”的结果,也就是说 await 在拿到这个结果之前不会执行后面的代码,会一直等到拿到这个结果才往后继续执行。

注意:

  • await 后面如果不是 Promise 对象会自动包装成 Promise 对象。
  • await 只能在 async 函数内部使用,否则会报错。

三、总结

一句话,async 函数就是 Generator 函数的语法糖。

// Promise chain
ajax('/api/url1')
.then(value => {
return ajax('ajax/url2')
})
.then(value => {
return ajax('ajax/url3')
})
.then(value => {
return ajax('ajax/url4')
})
.catch(error => {
// 捕获异常
console.error(error)
})

Generator 优化多回调异步:

// 定义一个 generator 函数,ajax 返回一个 promise 对象
function* main() {
try {
const users = yield ajax('/api/users.json')
console.log(users)

const posts = yield ajax('/api/posts.json')
console.log(posts)

const urls = yield ajax('/api/urls.json')
console.log(urls)
} catch (e) {
// 捕获异常
console.log(e)
}
}

ES8(ES2017)提供的 Async/Await 是标准的异步编程语法,如果遇到多回调的 promise,可以使用 async 简化,效果和语法都和 Generator 一样,不用定义执行器,简单便捷。

asyncawait 优化多回调异步:

async function main() {
try {
const users = await ajax('/api/users.json')
console.log(users)

const posts = await ajax('/api/posts.json')
console.log(posts)

const urls = await ajax('/api/urls.json')
console.log(urls)
} catch (e) {
// 捕获异常
console.log(e)
}
}

main()

从上面代码可看出,async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await