【源码共读】await-to.js

259 阅读2分钟

async/await

ES7推出的async/await用法,解决了早期异步解决方案回调函数的回调地狱问题。以同步的方式写异步的写法也比promise的链式调用写法更加符合编码逻辑习惯。

async/await其实是Generator 函数 + yield 的语法糖,在平时的业务代码工作中,我都是习惯用async/await处理异步请求,在每一个async函数里面都要把await的操作包裹在tryCatch中用于捕获错误,有时候可能都会忘记写tryCatch。 如果不使用tryCatch,异步操作中如果是reject或者是抛出错误,都会导致async函数执行中断,不会继续执行;await只会接收到异步操作成功的结果,不会拿到报错信息;由于以上两个问题,捕获错误很有必要。

如果不做错误处理:

任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

错误处理方式

// 1、放在tryCatch中
async function myFunction() {
  try {
    await somethingThatReturnsAPromise();
  } catch (err) {
    console.log(err);
  }
}

// 2、给await后面的promise添加catch错误捕获
async function myFunction() {
  await somethingThatReturnsAPromise()
  .catch(function (err) {
    console.log(err);
  });
}

以上的错误处理方式如果写多了会有点繁琐,await-to.js库通过对异步操作的结果做一个封装,能解决经常需要写tryCatch的繁琐。

await-to.js使用

const asyFn = async () => {
  // fetchApi()是一个异步请求
  const [error, res] = await to(fetchApi(), {
    err: 'Task was created for you'
  })
  console.log(error, res);
}

源码解析

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
export 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];
    });
}
export default to;

向外暴露一个to方法,方法接受两个参数,第一个参数是异步操作的promise,第二个参数是自定义的错误对象。 方法的返回值是一个长度为2的数组,第一个的值是错误对象,第二个的值是异步请求成功的数据。

通过对第一个参数promise的catch错误捕获,拿到异步请求的错误信息,与第二个参数中的错误对象做一个合并且作为数组的第一个值返回,使用者可以在await的返回值中同时拿到成功和错误数据。不用再多次书写tryCatch。