- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第21期,链接:【若川视野 x 源码共读】第21期 | await-to-js 如何优雅的捕获 await 的错误。
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];
});
}
- 该函数接受一个Promise对象和一个可选的errorExt对象作为参数。
- 该函数的返回值是一个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的问题。 总之,每个语法都有其优缺点。迭代才是王道🤔。