大白话说 async await ,面试专用
Async await
将异步写成同步的样子,并保证执行顺序,解决回调地狱的问题
如果你是写成回调地狱的样式,一个请求成功以后,在回调里面嵌套下一个回调,这样多级嵌套的回调函数弊端很多,不直观,强耦合性,回调的不确定性,不利于维护和复用
async await就解决了这个问题(最下方有案例参考)
1、async的作用
返回一个promise对象
async function test(){
return '随便测试'
}
打印出来(console.log(test)),就是一个promise对象
如果函数return一个直接量,async会痛殴promises.resolve()封装成promise对象,在没有await的情况下会立即执行(promise的特点-无等待),返回一个promise对象,不会阻塞后面的语句,只是返回promise对象的函数
2、await 等待什么
它等待的是后面的表达式,表达式的结果 === promise对象或者其他的值(没有限定的)
await不仅仅用于等待promise对象,可以等待任意表达式的结果,所以await后面可以接普通的函数调用或者直接量
3、await等到以后呢?
a、如果等待的不是一个promise对象,那么await的运算结果就是它要等到的东西
b、等到的是promise,await就会阻塞后面的代码,等着promise对象resolve,然后得到resolve的值,作为await表达式的结果
这就是await 必须用在async函数中的原因,async函数调用不会造成阻塞,它的内部所有的阻塞都被封装在一个promise对象中异步执行
换句话说:async将后面的函数封装成一个promise对象, await会等待这个promise完成,并将其resolve的结果返回出来
案例:
1、如果你想让接口有顺序的执行(有依赖性),比如执行完A接口我才可以执行B接口,你可以写成嵌套的样子(回调地狱),A的请求成功后调用B,但是多成的嵌套有很多缺点,也不美观
使用async await 结局
async function test(){
const callback1 = await this.handleQuestApiA()// 请求A接口的函数(如果你需要返回值,记得在函数是中return 出ajax和结果,不需要返回值,可以直接 await this.handleQuestApiA() )
const callback1 = await this.handleQuestApiB()// 请求b接口的函数(如果你需要返回值,记得在函数是中return 出ajax和结果,不需要返回值,可以直接 await this.handleQuestApiA() )
}
test()
你可以通过控制台,调节网速,调的慢一点,就可以看到接口A在pengding的时候,没有请求接口B,只有在A请求完成后,B接口才开始进行请求,比回调地狱好维护的多
2、你希望接口A、和接口B同时进行请求,可以使用forEach、map循环,把await就放在子函数里面就可以了
案例:
async function test2(){
const Arr = [1,2] //声明一个数组
Arr.forEach((item,index)=>{
if( index === 0 ){
this.handleQuestApiA()
}else if(){
this.handleQuestApiB()
}
})
}
这个时候接口A和接口B就是并发执行的,两个接口同时进行
原因:forEach只是简单的执行下回调函数,并不会处理异步的情况