es6——async / await
程序员文章站
2023-12-21 21:43:10
...
首先,async / await
是什么?简单来说,它就是 Generator 函数的语法糖
特点:
- 内置执行器
Generator 函数执行必须靠执行器,所以才有了 co 模块,而 async 函数自带执行器,也就是说 async 函数的执行与普通函数一摸一样,只要一行 - 更好的语义
async 和 await 比起星号和 yield,语义更加清晰,async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果 - 更广的使用性
co 模块约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作) - 返回值是 Promise
async 函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便许多,可以 then 和 catch 方法指定下一步操作
进一步说,async 函数可以看作由多个异步操作包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖
async 函数多种形式
// 函数声明
async function foo () {}
// 函数表达式
const foo = async function () {}
// 对象的方法
let obj = { async foo () {} }
obj.foo().then()
// Class 的方法
class Storage {
constructor () {
this.cachePromise = caches.open('avatars')
}
async getAvatar (name) {
const cache = await this.cachePromise
return cache.match(`/avatar/${name}.jpg`)
}
}
const storage = new Storage()
storage.getAvatar('jake').then()
// 箭头函数
const foo = async () => {}
async 用法
async function asyncFun () {
let name = await db.get(name)
let result = await db.get(name)
return result
}
asyncFun()
.then(res => {
console.log(res)// 返回 return 的 result
})
.catch(err => {
console.log(err)// 发生错误在这里捕获
})
async 函数中间一步 await 出错或遇到 return,后面的 await 都会停止执行,抛出的错误对象会被 catch 方法回调函数接收到
注意:await 命令后面的 Promise 对象的运行结果可能是 rejected,所以最好把 await 命令放在 try … catch 代码块中
// 结合 try ... catch 使用
async function asyncFun () {
try {
let name = await db.get(name)
let result = await db.get(name)
return result
} catch (e) {
console.log(e)// 发生错误在这里捕获
}
}
asyncFun().then(res => {
console.log(res)// 返回 return 的 result
})
多个 await 命令后面的异步操作如果不存在继发关系,最好让它们同时触发
// 这种执行方式,由于 getFoo 和 getBar 是两个独立的异步操作(互不依赖)
// 被写成继发关系,比较耗时,只有 foo 完成后才会执行 bar
let foo = await getFoo()
let bar = await getBar()
// 解决的两种方式:
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()])
// 写法二
let fooPromise = getFoo()
let barPromise = getBar()
let foo = await fooPromise
let bar = await barPromise