js中的async,await与Promise
序
最近在研究arco design代码,翻看到axios的response的拦截器时,被一段代码搞困惑了,代码如下
axios.interceptors.response.use(
(response: AxiosResponse<HttpResponse>) => {
const res = response.data;
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) {
...省略代码若干
return Promise.reject(new Error(res.msg || 'Error'));
}
return res
},
(error) => {}
重点就在这段代码里的return返回的数据,他返回了不同类型的数据,一个是返回了Promise对象,一个返回了普通数据,那我应该如何统一处理这个返回结果呢。
平常都是用的Promise对象,对异步处理都是标准的
new Promise().then().catch()
如果拦截器里返回的都是Promise对象,我也不会困惑了,但是这个拦截器可能返回异步对象,可能返回普通数据,总不能给普通数据也用then和catch吧。
本着绝不放过一个困惑宗旨,探究一番。
一 js中的异步方案
同步与异步
同步就是cpu执行代码时候一条一条执行,按顺序同步着执行。
异步就是cpu同时执行不同的功能代码,比如边播放视频,边放声音。
编程语言中的异步方案
各种编程语言都有异步解决方案,无非是协程,线程,进程。
js是单线程,采用协程方案实现并发。
同步事件是一个容易理解的事情,但异步事件却是一个反直觉的事情,所以各编程语言在语法层面上前仆后继,想要消灭这种反直觉的事情。
js也不例外,异步方案经历了好次多迭代。
Promise 对象
Promise对象是一个异步对象,经典使用方式如下: 假设定义了一个请求异步对象,网络请求总会是个耗时的事情,不可能只干等着请求结果,不去处理别的事情了。
var request = new Promise((ok,bad)=>{
//一段时间后
//如果成功
ok("ok")
//如果失败
bad("error")
})
这就是一个常见的异步对象定义,那如何使用?
request.then(ok=>{
console.log(ok)
}).catch(err=>{
console.log(err)
})
异步对象都有then,catch,finally三个api函数,分别用来处理不同结果,then处理正确的结果,catch处理异常结果,finally不管结果如何都会调用。
注意,这三个函数都是回调函数,这段代码执行后不会停留,也就是异步执行then,catch,和finally的代码。什么时候request有结果了就通知对应的回调函数调用。
这种语法比js最开始的纯回调函数实现的异步方案已经是一个进步了,纯回调函数实现的异步方案有可能造成恐怖的回调地狱现象。
promise要是碰上回调地狱只能说,略好。
request1.then(ok=>{
request2.then(ok=>{
request3.then(ok=>{
...
})
})
})
async await
js中的异步方案还是要看async和await,这是一种用同步思维编写异步代码的方案。当然是最容易使用的一种方案。
使用规则:
- async用于修饰定义函数,会对返回值进行promise包装。
var asyncFun = async function(){
return "this async ok"
}
var asyncFun2 = async function(){
throw("this is async error")
}
var asyncFun3 = async function(){
return Promise.resolve("this is promise")
}
console.log("async返回结果:")
console.log(asyncFun())
console.log(asyncFun2())
console.log(asyncFun3())
//返回结果如下
// async返回结果:
// Promise {<fulfilled>: 'this async ok'}
// Promise {<rejected>: 'this is async error'}
// Promise {<pending>}
- await 只能用在被async修饰的函数中。
var asyncFun3 = function(){
var msg = await "this is a" //此处有语法错误
return msg
}
- await 后可以跟任何数据,包括promise对象,和非promise对象。如果后边跟着promise对象会对promise的执行结果做处理,如果是resolve则直接返回,如果是reject则抛出异常throw。
var async4 = async function(){
var msg = await asyncFun()
console.log("await ok result:",msg)
try{
await asyncFun2()
}catch(err){
console.log("await err result:",err)
}
}
async4()
//打印结果
// await ok result: this async ok
// await err result: this is async error
结论
从规则中可以看出,async可以更容易的生成promise对象,而await则可以用同步的方法去使用异步方法,async是promise的打包,await则是promise的拆包。
await后如果跟非promis对象,其实效果和没有await一样,所以最开始的困惑这里就能解开了,await可以对后边跟着的结果做动态处理,处理的结果都一样,都是普通js类型的数据或者抛出异常。
转载自:https://juejin.cn/post/7205908717887143997