I'm completely new to rxjs and trying to accomplish one task - essentially I need a Promise-like API with the following differences:
Promise
my API should be able to resolve
multiple times.await
/then
the last resolved value should be used.await
/then
should hung up, just like the standard Promise
.reset
method which will be resetting my API object so the following await
/then
calls will hung up like in the point 3.How can I implement the needed behaviour? I think rxjs Observable
and lastValueFrom
is what I need, but I just can't figure out how to use it.
Pseudocode example usage:
const myAuthObservable = new MyObservableApi<Auth>((resolve) =>
subscribe(
(s) => s.auth,
(auth) => {
if (auth) {
resolve(auth); // this can be called multiple times
}
}
)
);
emitter.on("start", async () => {
// always the last auth will be returned
// or the api will hung up until the first auth is emitted
const auth = await myAuthObservable;
myAuthObservable.reset();
});
after reading @Barmar comment I eventually came up with a simple non-rxjs solution
It sounds like what you want is an object that caches the value that the promise resolves to, then returns that cached value on future uses
export class MultiResolve<T> {
private readonly initialSymbol: symbol = Symbol();
private currentValue: T | symbol = this.initialSymbol;
private readonly resolvers: Array<(value: T) => void> = [];
resolve(value: T): void {
this.currentValue = value;
for (const resolver of this.resolvers) {
resolver(value);
}
}
get promise(): Promise<T> {
return new Promise(resolve => {
if (this.currentValue !== this.initialSymbol) {
resolve(this.currentValue as T);
}
this.resolvers.push(resolve);
});
}
reset(): void {
this.currentValue = this.initialSymbol;
}
}
usage:
const multiResolve = new MultiResolve<number>();
async function test() {
console.log(await multiResolve.promise); // Will wait until the first resolve
multiResolve.resolve(1);
console.log(await multiResolve.promise); // Will immediately get 1
multiResolve.resolve(undefined as any); // TypeScript requires an explicit cast to 'any' for undefined
console.log(await multiResolve.promise); // Will immediately get undefined
multiResolve.resolve(2);
console.log(await multiResolve.promise); // Will immediately get 2
}
test();
setTimeout(() => {
multiResolve.resolve(3); // Will immediately get 3 in the next await
}, 1000);