理解async/await的原理
了解过了promise之后,就不得不提一个东西,那就是
是一个很重要的async/await,
async/await语法糖
,他的作用是用同步的方式,执行异步操作。
要实现一个东西之前,最好是先搞清楚这两样东西
- 这个东西有什么用?
- 这个东西是怎么用的?
一、有什么用?
async/await
的用处就是:用同步方式,执行异步操作,怎么说呢?举个例子
比如我现在有一个需求:先请求完接口1
,再去请求接口2
,我们通常会这么做
function request(num) { // 模拟接口请求 return new Promise(resolve => { setTimeout(() => { resolve(num * 2) }, 1000) }) } request(1).then(res1 => { console.log(res1) // 1秒后 输出 2 request(2).then(res2 => { console.log(res2) // 2秒后 输出 4 }) })
或者我现在又有一个需求:先请求完接口1
,再拿接口1
返回的数据,去当做接口2
的请求参数,那我们也可以这么做
request(5).then(res1 => { console.log(res1) // 1秒后 输出 10 request(res1).then(res2 => { console.log(res2) // 2秒后 输出 20 }) })
其实这么做是没问题,但是如果嵌套的多,不免有点不雅观,可读性维护性不高,代码显得也很臃肿,这个时候就可以用async/await
来解决了
async function fn () { const res1 = await request(5) const res2 = await request(res1) console.log(res2) // 2秒后输出 20 } fn()
二、怎么用?
还是上面的例子
//需求一 async function fn () { await request(1) await request(2) // 2秒后执行完 } fn() //需求二 async function fn () { const res1 = await request(5) const res2 = await request(res1) console.log(res2) // 2秒后输出 20 } fn()
就类似于生活中的排队
,咱们生活中排队买东西,肯定是要上一个人买完,才轮到下一个人。而上面也一样,在async
函数中,await
规定了异步操作只能一个一个排队执行,从而达到用同步方式,执行异步操作的效果
注意:await只能在async函数中使用,不然会报错
刚刚上面的例子await
后面都是跟着异步操作Promise
,那如果不接Promise
会怎么样呢?
function request(num) { // 去掉Promise setTimeout(() => { console.log(num * 2) }, 1000) } async function fn() { await request(1) // 2 await request(2) // 4 // 1秒后执行完 同时输出 } fn()
可以看出,如果await
后面接的不是Promise
的话,有可能其实是达不到排队
的效果的
说完await
,继续看下async
,async
是一个位于function之前的前缀,只有async函数
中,才能使用await
。那async
执行完是返回一个什么呢?
async function fn () {} console.log(fn) // [AsyncFunction: fn] console.log(fn()) // Promise {<fulfilled>: undefined}
可以看出,async函数
执行完会自动返回一个状态为fulfilled
的Promise,也就是成功状态,但是值却是undefined,怎么才能使值不是undefined呢?需要函数有return
返回值就行了
async function fn (num) { return num } console.log(fn) // [AsyncFunction: fn] console.log(fn(10)) // Promise {<fulfilled>: 10} fn(10).then(res => console.log(res)) // 10
此时就有值了,并且还能使用then方法
进行输出
三、总结
- await只能在async函数中使用,不然会报错
- async函数返回的是一个Promise对象,有无值看有无return值
- await后面最好是接Promise,虽然接其他值也能达到排队效果
- async/await作用是用同步方式,执行异步操作
四、什么是语法糖?
前面说了,async/await
是一种语法糖
,啥是语法糖
呢?其实语法糖
就是一个东西,这个东西你就算不用他,你用其他手段也能达到这个东西同样的效果,但是可能就没有这个东西这么方便。
举个生活中的例子吧:你走路也能走到北京,但是你坐飞机会更快到北京。
举个代码中的例子吧:ES6的class
也是语法糖,因为其实用普通function
也能实现同样效果
回归正题,async/await
是一种语法糖
,那就说明用其他方式其实也可以实现他的效果,我们今天就是讲一讲怎么去实现async/await
,用到的是ES6里的迭代函数——generator函数