源码阅读】听说你还在单独为 await 做 try catch?要不进来瞅瞅?

65 阅读2分钟

await-to-js 源码

源码地址: await-to-js

了解到await to 是通过propmise自带的catch来解决,外面的try-catch,使得代码看起来更加的干净和优雅。

/** 
* @param { Promise } promise 
* @param { Object= } errorExt - Additional Information you can pass to the err object 
* @return { Promise } 
*/
export function to<T, U = Error> (
  promise: Promise<T>,
  errorExt?: object
): Promise<[U, undefined] | [null, T]> {
  return promise
    .then<[null, T]>((data: T) => [null, data])
    .catch<[U, undefined]>((err: U) => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt);
        return [parsedError, undefined];
      }

      return [err, undefined];
    });
}
  1. 该函数接受一个Promise对象和一个可选的errorExt对象作为参数。
  2. 该函数的返回值是一个Promise对象,该Promise对象在成功时返回一个包含null和Promise对象的元组,失败时返回一个包含错误对象和undefined的元组。

测试用例

describe('Await to test', async () => {
  it('should return a value when resolved', async () => {
    const testInput = 41;
    const promise = Promise.resolve(testInput);

    const [err, data] = await to<number>(promise);

    expect(err).toBeNull();
    expect(data).toEqual(testInput);
  });

  it('should return an error when promise is rejected', async () => {
    const testInput = 41;
    const promise = Promise.reject('Error');

    const [err, data] = await to<number>(promise);

    expect(err).toEqual('Error');
    expect(data).toBeUndefined();
  });

  it('should add external properties to the error object', async () => {
    const promise = Promise.reject({ error: 'Error message' });

    const [err] = await to<
      string,
      { error: string; extraKey: number }
    >(promise, {
      extraKey: 1
    });

    expect(err).toBeTruthy();
    expect((err as any).extraKey).toEqual(1);
    expect((err as any).error).toEqual('Error message')
  });

  it('should receive the type of the parent if no type was passed', async () => {
    let user: { name: string };
    let err: Error;

    [err, user] = await to(Promise.resolve({ name: '123' }));

    expect(user.name).toEqual('123');
  });
});

总结

早期异步请求中,由于回调函数的过多嵌套,导致代码难以阅读和维护,产生了“回调地狱”。为了解决这个问题,ES6的promise对象由此诞生了,通过它可以对callback的回调地狱进行优化,但.then书写多了也会产生难以阅读和维护的问题。ES7的时候推出了 async/await,基于Promise的语法糖。但是每次处理异常都要手动添加try catch。await-to库,则解决了每次都要手动try catch的问题。 总之,每个语法都有其优缺点。迭代才是王道🤔。