【若川视野 x 源码共读】第23期 | await-to-js 如何优雅的捕获 await 的错误

123 阅读2分钟

前言

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。

背景回顾

CallBack 回调函数

在之前,我们通过ajax方法在处理接口返回数据时,是需要CallBack(回调函数)来处理的,如下

$.ajax({
    url,
    success:function(result){},
    error:function(error){}
});

我们都知道,之前的异步处理,会存在回调地域,就是多个回调函数会一层套一层,类似俄罗斯套娃,整个项目维护起来比较困难,且代码的阅读性也会大打折扣,如下

$.ajax({
  url1,
  success:function(result){
    $.ajax({
      url2,
      success:function(result){
        $.ajax({
          url3,
          success:function(result){
            ...
            $.ajax({
              urln,
              success:function(result){
​
              },
              error:function(error) {}
            })
            ...
          },
          error;function(error){}
        })
      },
      error:function(error){}
    })
  },
  error:function(error){}
});

Promise 异步函数

Promise是一个ES6提供的方法,目的是更加优雅地书写复杂的异步任务。

Promise的出现,让我们能够将原来的回调地域改成链式调用形式,有效弥补了之前的不足,之前的例子可优化如下

axios(url1)
  .then(() => {
    return axios(url2)  
  })
  .then(() => {
    return axios(url3)
  })
  ...
  .then(() => {
    return axios(urln)
  })
  ...
  .catch((error) => {
    console.log("异常")
  })

async/await 异步函数

async/awaitES7Promise的升级处理,将异步方法通过通过同步方法进行处理,使得分步流程更加清晰明了,如下

async function asyncFun() {
  const result1 = await Promise1();
  const result2 = await Promise2();
  const result3 = await Promise3();
  ...
  const resultn = await Promisen();
  ...
}

毋庸置疑,async/await让整体的代码可读性和维护性更加方便简单,但是其也存在一个很棘手的问题,就是针对异常报错的处理,需要通过try/catch,这无形中有增加的代码量

async function asyncFun() {
  try {
    const result1 = await Promise1();
  } catch(err) {
    console.log('异常');
    return;
  }
​
  try {
    const result2 = await Promise2();
  } catch(err) {
    console.log('异常');
    return;
  }
  
  ...
  const resultn = await Promisen();
  ...
}

我们会发现,我们写了大量重复的代码,来处理await的异常。那我们可不可以将try/catch封装起来,在await的结果里直接返回其正常和异常结果,那我们处理起来是不是就很方便了。

由此,我们引出await-to-js

await-to-js

await-to-js是一个异步函数结果处理器,便于处理异常错误。说白了,就是处理Promise的返回结果的。

源码

我们来看下源码,比较简单

function to(promise, errorExt) {
    return promise
        .then(function (data) { return [null, data]; })
        .catch(function (err) {
        if (errorExt) {
            var parsedError = Object.assign({}, err, errorExt);
            return [parsedError, undefined];
        }
        return [err, undefined];
    });
}

to方法接受两个参数,promise(必传的Promise对象)和 errorExt(自定义的错误信息)

使用

async function asyncFun() {
​
  const [err1, result1] = await to(promise1)
  if(err1) return;
​
  const [err2, result2] = await to(promise2);
  if(err2) return;
  
  ...
  const [errn, resultn] = await to(promisen);
  if(errn) return
  ...
}

通过await-to-js,我们对promise做了一个封装,处理了promise结果。