在前端开发中,异步编程的场景越来越多,如网络IO,文件IO

随着时间的推移,异步编程的解决方案也在不断改进,从最初的 callback,到后来的 promise和generator,再到终极解决方案 async,await

因为方案的改进,我们也可以越来越方便地处理异步场景,这篇文章就准备聊聊终极方案:async和await,废话不多说,开搞!

ppx.jpg

什么是async,await

async和await是处理 异步编程 的一种解决方案,并且是 promise以及generator 的语法糖,可以使我们以 同步编码 的方式实现异步编程的目的

wocao.jpeg

既然是promise以及generator的语法糖,那么它做了哪些改进呢?列举如下

  1. 内置执行器:对于generator函数,我们需要通过调用 next 方法来 手动 控制其执行过程,但async函数的执行完全是 自动的

  2. 更好的语义: async和await 比起 星号和yield,语义更清楚了,async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果

  3. 返回值的优化: async函数的返回值是 Promise对象,这比Generator函数的返回值是 Iterator对象 方便多了,可以用 then 方法指定下一步的操作

  4. 获取异步操作返回值的优化: promise想要获取返回值,必须跟上then来获取,而async函数里,直接使用await就可以以同步的方式获取返回值

如何使用async,await

先给出一个简单示例

1
2
3
4
5
6
7
async function example() {
const data = await request('https://www.baidu.com')
return data
}
example().then(res=>{
console.log(res)
})

可以看到async,await的使用非常简单,关键点如下:

  1. 在普通函数之前添加 async 关键字,使其成为async函数
  2. 在函数内部,存在异步操作的地方,就使用 await,用来获取与存放异步操作的返回值
  3. 由于async函数调用后是返回一个promise对象,因此如果想传递参数给promise对象的then方法,就需要在async函数里return返回值

使用async,await需要注意的地方

使用方式上,async和await很简单,没有太多可说的,但是实际使用时,还是有一些需要注意的地方,列举如下

  1. 如果在async函数里 抛错了,则会被返回的promise的 catch方法 捕获,需要注意,一旦抛错了,那么后续语句就不会再执行
  2. 通常情况下,await后面跟的是一个promise并返回对应的结果,但是也可以跟非promise对象,此时就直接返回该非promise对象的值
  3. 任何一个 await 语句后面的 Promise 对象变为 reject 状态,那么整个 async 函数都会中断执行,并且async函数返回的promise会变为 reject 状态
  4. 如果 await 后面的异步操作里抛错,那么整个 async 函数都会中断执行,并且async函数返回的promise会变为 reject 状态
  5. 对于3,4的解决方案,有两种,一是使用 try和catch,二是给await后面的promise加上 catch语句
  6. async函数可以 保留 运行堆栈

结语

最近我开始了思维导图的学习之路,我的打算是在以后每篇文章中,都附上一张思维导图,从而可以帮助理解文章脉络,形成结构性思维,最终提升对浩如烟海的知识的掌握程度,所以,一起努力吧,骚年!