Skip to content

Commit

Permalink
feat: LazyPromise
Browse files Browse the repository at this point in the history
  • Loading branch information
Soontao committed Apr 1, 2021
1 parent deef645 commit 0f2b34b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 2 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"cSpell.words": [
"Deno",
"Mutex",
"Theo",
"falsey",
"newdash",
"nocheck"
Expand Down
61 changes: 61 additions & 0 deletions src/async/LazyPromise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@


/**
* @internal
*/
type Executor<T = any> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void

/**
* @internal
*/
const GlobalPromise = Promise;

/**
* LazyPromise, execute async operation when user await it.
*
* @author Theo Sun
*
* @category Async
* @since 5.18.0
*/
export class LazyPromise<T = any> implements Promise<T> {

private _executor: Executor<T>
private _promise: Promise<T>

/**
* LazyPromise, execute async operation when user await it.
*
* @param executor Promise executor
*/
constructor(executor: Executor<T>) {
this._executor = executor;
}

[Symbol.toStringTag]: string;

private _getPromise(): Promise<T> {
if (this._promise === undefined) {
this._promise = new GlobalPromise(this._executor) as any;
}
return this._promise;
}

then<TResult1 = T, TResult2 = never>(
onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>,
onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2> {
return this._getPromise().then(onfulfilled, onrejected);
}

catch<TResult = never>(
onrejected?: (reason: any) => TResult | PromiseLike<TResult>
): Promise<T | TResult> {
return this._getPromise().catch(onrejected);
}

finally(onfinally?: () => void): Promise<T> {
return this._getPromise().finally(onfinally);
}


}
1 change: 1 addition & 0 deletions src/async/allSettled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface SettleResult<T = any> {
/**
* Promise.allSettled() implementation
*
* @author Theo Sun
* @since 5.18.0
* @category Async
* @param collection
Expand Down
1 change: 1 addition & 0 deletions src/async/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { AsyncFunction } from '../types';
/**
* AsyncUtils.filter, filter values by async predicate function
*
* @author Theo Sun
* @since 5.18.0
* @category Async
* @param collection
Expand Down
4 changes: 2 additions & 2 deletions src/async/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { any } from '../any';
import { allSettled } from './allSettled';
import { filter } from './filter';
import { LazyPromise } from './LazyPromise';
import { map } from './map';


/**
* AsyncUtils
*
* @since 5.18.0
*/
export const AsyncUtils = {
filter, map, allSettled, any
filter, map, allSettled, any, LazyPromise
};

export default AsyncUtils;
1 change: 1 addition & 0 deletions src/async/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { allSettled } from './allSettled';
*
* AsyncUtils.map, mapping values with async iteratee functions
*
* @author Theo Sun
* @since 5.18.0
* @category Async
* @param collection
Expand Down
26 changes: 26 additions & 0 deletions test/AsyncUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from 'assert';
import { sleep } from '../src';
import { AsyncUtils } from '../src/async';
import { LazyPromise } from '../src/async/LazyPromise';

describe('AsyncUtils Test Suite', () => {

Expand All @@ -25,4 +26,29 @@ describe('AsyncUtils Test Suite', () => {
assert.deepStrictEqual(values, [1, 4, 9]);
});

it('should support lazy promise', async () => {

let v = 0;

const p = new LazyPromise<number>((resolve) => {
v = 1;
resolve(1);
});

await sleep(50);
expect(v).toBe(0);
await p;
expect(v).toBe(1);

const p2 = new LazyPromise((resolve, reject) => {
v = 2;
reject(new Error);
});

await sleep(50);
expect(v).toBe(1);
expect(p2).rejects.toThrow();
expect(v).toBe(2);
});

});

0 comments on commit 0f2b34b

Please sign in to comment.