(ctor: TClass)
| 7 | import { ConstructorReturn, Reject, Resolve, AsyncConstructor } from '../System/types'; |
| 8 | |
| 9 | export function Async<TClass extends new (...args: ConstructorParameters<TClass>) => ConstructorReturn<TClass>>(ctor: TClass) { |
| 10 | class AsyncConstructed extends Promise<TClass> { |
| 11 | static class: TClass = ctor; |
| 12 | constructor(...args: ConstructorParameters<TClass>); |
| 13 | constructor(...args: any[]) { |
| 14 | |
| 15 | if (args.length === 1 && typeof args[0] === 'function') { |
| 16 | // this is being called because a new Promise is being created for an async function invocation (not user code) |
| 17 | super(args[0]); |
| 18 | return; |
| 19 | } |
| 20 | |
| 21 | // this is being called because a user is creating an instance of the class, and we want to call the init() method |
| 22 | super((resolve: Resolve<TClass>, reject: Reject) => { |
| 23 | try { |
| 24 | // call the constructor with the arguments that they provided |
| 25 | const instance = new ctor(...(args as any)) as any; |
| 26 | |
| 27 | // if .init is a function, call it |
| 28 | const pInit = typeof instance.init === 'function' ? instance.init(...args) : instance.init; |
| 29 | |
| 30 | // if the result of .init is a promise (or is a promise itself), then on completion, it should propogate the result (or error) to the promise |
| 31 | if (is.promise(pInit)) { |
| 32 | pInit.then(() => resolve(instance)).catch(reject); |
| 33 | } else { |
| 34 | // otherwise, the result of init is not a promise (or it didn't have an init), so just resolve the promise with the result |
| 35 | resolve(instance); |
| 36 | } |
| 37 | } catch (error) { |
| 38 | // if the constructor throws, we should reject the promise with that error. |
| 39 | reject(error); |
| 40 | } |
| 41 | }); |
| 42 | } |
| 43 | } |
| 44 | // return a new constructor as a type that creates a Promise<T> |
| 45 | return AsyncConstructed as any as AsyncConstructor<TClass>; |
| 46 | } |
no outgoing calls
no test coverage detected