likes
comments
collection
share

js中的async,await与Promise

作者站长头像
站长
· 阅读数 13

最近在研究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>}
  1. await 只能用在被async修饰的函数中。
 var asyncFun3 =  function(){
      var msg = await "this is a" //此处有语法错误
      return msg
  }
  1. 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类型的数据或者抛出异常。