For some Typescript methods I build, often I need the asynchronicity of a promise but I do not require the promise to return a value (conceptually speaking). A simple example might be calling an initLanguageStrings( ) method to load up language strings used by an application. The language strings are placed into a global structure but the promise is still necessary to ensure the application does not continue until after the language strings are loaded.
Multiple this scenario two or three times and I then tie all of the initialisation work into a set of promises that collectively must all be completed before continuing. I therefore use Promise.all, like so (example):
initialiseApp( ): Promise< void >
{
let promises: Promise< any >[ ] = [ ];
promises.push( this.initLanguageStrings( ) );
promises.push( this.initModelData( ) );
promises.push( this.initUserInfo( ) );
return Promise.all( promises );
}
The above code won't actually compile (TS1.5/1.6) because Promise.all( ) returns Promise< any[ ] > not Promise< void >.
So what I end up writing is this:
return new Promise( ( resolve, reject ) => {
Promise.all( promises )
.then( ( dummy: any[ ] ) => {
resolve( );
} );
} );
I believe this is semantically the correct approach, because the "implementation" actually remains hidden, and the "inner promise" (from Promise.all) never "escapes" to the caller of initialiseApp( ).
But on the other hand I find this approach ugly, and would like to find a nicer way to do this, since returning Promise< void > is becoming quite a common pattern for me.
Is there a better way to achieve what I am trying to do?
The compiler will permit:
return Promise.all( promises ).then( ( ) => { } );
But it too strikes me as "tricky" and ugly.
Use the Awaited utility type to get the return type of a promise in TypeScript, e.g. type A = Awaited<Promise<string>> . The Awaited utility type is used to recursively unwrap Promises and get their return type. Copied!
In TypeScript, promise type takes an inner function, which further accepts resolve and rejects as parameters. Promise accepts a callback function as parameters, and in turn, the callback function accepts two other parameters, resolve and reject. If the condition is true, then resolve is returned; else, returns reject.
Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.
To access the value of a promise in TypeScript, call the then() method on the promise, e.g. p. then(value => console. log(value)) . The then() method takes a function, which is passed the resolved value as a parameter.
since returning Promise< void > is becoming quite a common pattern for me
You can use a type assertion
initialiseApp( ): Promise< void >
{
let promises: Promise< any >[ ] = [ ];
promises.push( this.initLanguageStrings( ) );
promises.push( this.initModelData( ) );
promises.push( this.initUserInfo( ) );
return Promise.all( promises ) as Promise<void>;
}
Note : when you use an assertion you are essentially lying to the compiler in this case. Be careful about bugs where the compiler thinks one thing and the runtime sees another.
return Promise.all( promises ).then( ( ) => { } );
This is the right way to do it. The runtime matches what the compiler has inferred. If you want a Promise<void>
... then make a Promise<void>
which is what this code sample does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With