Skip to content

Commit 48dbfd5

Browse files
committed
feat: add safeAwait func
1 parent 5bf86e5 commit 48dbfd5

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

src/async.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,35 @@ export function asyncMap<T, R>(
5959
}
6060
});
6161
}
62+
63+
/**
64+
* Execute a promise safely
65+
*
66+
* @param { Promise } promise
67+
* @param { Object= } errorExt - Additional Information you can pass to the err object
68+
* @return { Promise }
69+
* @example
70+
* async function asyncTaskWithCb(cb) {
71+
let err, user, savedTask, notification;
72+
73+
[ err, user ] = await to(UserModel.findById(1));
74+
if(!user) return cb('No user found');
75+
76+
[ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
77+
if(err) return cb('Error occurred while saving task')
78+
79+
cb(null, savedTask);
80+
}
81+
*/
82+
export function safeAwait<T, U = Error>(promise: Promise<T>, errorExt?: object): Promise<[U, undefined] | [null, T]> {
83+
return promise
84+
.then<[null, T]>((data: T) => [null, data])
85+
.catch<[U, undefined]>((err: U) => {
86+
if (errorExt) {
87+
const parsedError = Object.assign({}, err, errorExt);
88+
return [parsedError, undefined];
89+
}
90+
91+
return [err, undefined];
92+
});
93+
}

test/async.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { asyncMap, wait } from '../src/async';
1+
import { asyncMap, safeAwait, wait } from '../src/async';
22

33
test('wait', () => {
44
return new Promise(done => {
@@ -40,3 +40,46 @@ test('asyncMap 并发', async () => {
4040
);
4141
expect(fn).toBeCalled();
4242
});
43+
44+
describe('Await safeAwait test', () => {
45+
test('should return a value when resolved', async () => {
46+
const testInput = 41;
47+
const promise = Promise.resolve(testInput);
48+
49+
const [err, data] = await safeAwait<number>(promise);
50+
51+
expect(err).toBeNull();
52+
expect(data).toEqual(testInput);
53+
});
54+
55+
test('should return an error when promise is rejected', async () => {
56+
const testInput = 41;
57+
const promise = Promise.reject('Error');
58+
59+
const [err, data] = await safeAwait<number>(promise);
60+
61+
expect(err).toEqual('Error');
62+
expect(data).toBeUndefined();
63+
});
64+
65+
test('should add external properties safeAwait the error object', async () => {
66+
const promise = Promise.reject({ error: 'Error message' });
67+
68+
const [err] = await safeAwait<string, { error: string; extraKey: number }>(promise, {
69+
extraKey: 1
70+
});
71+
72+
expect(err).toBeTruthy();
73+
expect((err as any).extraKey).toEqual(1);
74+
expect((err as any).error).toEqual('Error message');
75+
});
76+
77+
test('should receive the type of the parent if no type was passed', async () => {
78+
let user: { name: string };
79+
let err: Error;
80+
// @ts-ignore
81+
[err, user] = await safeAwait(Promise.resolve({ name: '123' }));// eslint-disable-line
82+
83+
expect(user.name).toEqual('123');
84+
});
85+
});

0 commit comments

Comments
 (0)