解决async/await中如何监控失败问题:promise返回错误reject的问题

555 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

问题: await Promise, 只能接收到成功的 resolve() 的结果, 对于 reject() 的结果会报错。

解决办法: try-catch来处理同步逻辑

function test () {
    return new Promise((resolve, reject) => {
        this.$axios("请求地址").then((res) => {
            if (res.data.status === 200) {
                resolve(res.data.result) // 请求成功会回调
            } else {
                reject("err") // 请求失败会回调
            }
        })
    })
}

async fun () {
    try {
        cosnt testRes = await this.test()
        console.log(testRes)
    } catch (err) {
        console.log(err) // 请求错误会执行,结果为 err
    }
} 

更优雅的解决方式 await-to-js

如果只有1个请求,try catch倒是不错。但是如果有多个异步操作,需要对每个异步返回的 error 错误状态进行不同的处理,项目将会大量充斥着try catch,这就比较令人难以接受了。

function request(type) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            type === 'a' ? resolve('resolve') : reject('reject')
        }, 2000);
    })
}

async function getData() {
    try {
        let ret1 = await request('a');
    }catch(error){
        // todo 
    }

    try {
        let ret2 = await request('b');
    } catch (error) {
        // todo
    }

    try {
        let ret3 = await request('c');
    } catch (error) {
        // todo
    }
}
getData();

在复杂的业务中,这种充斥很多的try catch实在不够简洁。势必会想办法解决一下这个问题。 首先需要明确的是 await 后面的promise只有是一个resolve状态,才能正确的拿到其结果。那么要解决这个问题,势必要让异步返回一个resolve状态,但是错误我们不能视而不见,结合nodejs中错误优先,我们可以将错误和结果封装成一个数组返回,那么就有了await-to-js

await-to-js源码

源码总结: to函数返回一个Promise且值是一个数组,数组之中有两个元素,如果索引为0的元素不为空值,说明该请求报错,如果索引0的元素为空值说明该请求没有报错,也就是成功。

/**
 * @param { Promise } 传进去的请求函数
 * @param { Object= } errorExt - 拓展错误对象
 * @return { Promise } 返回一个Promise
 */
export function to(
  promise,
  errorExt
) {
  return promise
    .then(data => [null, data])
    .catch(err => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt)
        return [parsedError, undefined]
      }
 
      return [err, undefined]
    })
}
 
export default to

使用

const handleLogin = async () => {
    const [resErr, res] = await to(request('/basic/login', {
      usename: 'sunshine',
      password: '123456'
    }))
    if (resErr) {
      // fail do somthing
      return
    }
    const [userErr, info] = await to(request('/basic/getuserinfo', {
      id: res.id
    }))
    if (userErr) {
      // fail do somthing
      return
    }
    this.userInfo = info
}