本文参加了由公众号@若川视野发起的每周源码共读活动,点击了解详情一起参与。
目标
学习await-to-js用法及其原理
解决什么?
一般情况下处理async await 产生的异常,需要包裹一层try catch。await-to-js通过简单封装一层来处理造成异常。
如何使用?
安装
npm install await-to-js
例子
import { to } from 'await-to-js';
function findUserById(userId = 1) {
return new Promise((resolve, reject) => {
if (userId == -1) {
reject(new Error('userId 不能为 -1'));
} else {
resolve({
id: userId,
msg: '找到信息'
})
}
});
}
async function test() {
// 通过 to 包裹一层,返回形式为[err, data]
let [err1, data1] = await to(findUserById(2));
let [err2, data2] = await to(findUserById(-1));
console.log(err1, data1);
console.log(err2, data2);
}
test();
/*
输出结果:
null { id: 2, msg: '找到信息' }
Error: userId 不能为 -1
at file:///C:/Users/Administrator/Desktop/core-study/demo/test-await-to.js:6:14
at new Promise (<anonymous>)
at findUserById (file:///C:/Users/Administrator/Desktop/core-study/demo/test-await-to.js:4:10)
at test (file:///C:/Users/Administrator/Desktop/core-study/demo/test-await-to.js:18:32) undefined
*/
怎么实现?
了解了怎么使用之后,我们来看看它内部是怎么实现的:
/**
* @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]> {
// 通过传进来的promise函数,通过then catch 来进行一些数据处理
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];
});
}
export default to;
通过上面可以看到,内部其实就是多进行了数据封装而已。这边写下js形式~
export function to (promise,errorExt){
// 通过传进来的promise函数,通过then catch 来进行一些数据处理
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;
测试用例
通过test/await-to-js.test.ts可以看出,await-to-js包中采用的测试框架是jest。
从测试用例可以看出主要对参数的类型进行测试,主要是对四种情况进行测试:
- Promise.resolve
-
- 带参
- 不带参
- Promise.reject
-
- 带参
- 不带参
import { to } from '../src/await-to-js'
describe('Await to test', async () => {
it('should return a value when resolved', async () => {
const testInput = 41;
const promise = Promise.resolve(testInput);
// Promise.resovle 无参测试
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');
// Promise.reject 无参测试
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' });
// Promise.reject传参测试
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;
// Promise.resolve 传参测试
[err, user] = await to(Promise.resolve({ name: '123' }));
expect(user.name).toEqual('123');
});
});
总结
从 await-to-js 中可以学到的几点:
- async await中的异常处理方式,可通过try-catch包裹
- 有效的简单封装使得代码易于维护
- 了解到新的测试框架jest