序
最近在研究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,这是一种用同步思维编写异步代码的方案。当然是最容易使用的一种方案。
使用规则:
1.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>}
2.await 只能用在被async修饰的函数中。
var asyncFun3 =function(){var msg = await "this is a" //此处有语法错误return msg}
3.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类型的数据或者抛出异常。
最后
为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。
有需要的小伙伴,可以点击下方卡片领取,无偿分享