smartuniverse/ts/smartuniverse.classes.event.reactionrequest.ts
2023-07-25 11:33:13 +02:00

84 lines
2.7 KiB
TypeScript

import * as plugins from './smartuniverse.plugins.js';
import { UniverseChannel } from './smartuniverse.classes.universechannel.js';
import { ClientUniverseChannel } from './smartuniverse.classes.client.universechannel.js';
import { ReactionResult } from './smartuniverse.classes.event.reactionresult.js';
import { UniverseMessage } from './smartuniverse.classes.universemessage.js';
import { ClientUniverseMessage } from './smartuniverse.classes.client.universemessage.js';
export interface IReactionRequestConstructorOptions<
T extends plugins.typedrequestInterfaces.ITypedRequest
> {
method: T['method'];
}
export interface ICombinatorPayload<T extends plugins.typedrequestInterfaces.ITypedRequest> {
/**
* needed for tying responses to requests
*/
id: string;
typedRequestPayload: {
method: T['method'];
request: T['request'];
response: T['response'];
};
}
export class ReactionRequest<T extends plugins.typedrequestInterfaces.ITypedRequest> {
public method: T['method'];
constructor(optionsArg: IReactionRequestConstructorOptions<T>) {
this.method = optionsArg.method;
}
public async fire(
channelsArg: Array<UniverseChannel | ClientUniverseChannel>,
requestDataArg: T['request'],
timeoutMillisArg = 5000
) {
const subscriptionMap = new plugins.lik.ObjectMap<plugins.smartrx.rxjs.Subscription>();
const reactionResult = new ReactionResult<T>();
const requestId = plugins.isounique.uni();
for (const channel of channelsArg) {
subscriptionMap.add(
channel.subscribe(
(
messageArg:
| UniverseMessage<ICombinatorPayload<T>>
| ClientUniverseMessage<ICombinatorPayload<T>>
) => {
if (
messageArg.messageText === 'reactionResponse' &&
messageArg.payload.typedRequestPayload.method === this.method
) {
const payload: ICombinatorPayload<T> = messageArg.payload;
if (payload.id !== requestId) {
return;
}
reactionResult.pushReactionResponse(payload.typedRequestPayload.response);
}
}
)
);
const payload: ICombinatorPayload<T> = {
id: requestId,
typedRequestPayload: {
method: this.method,
request: requestDataArg,
response: null,
},
};
channel.postMessage({
messageText: 'reactionRequest',
payload,
});
}
plugins.smartdelay.delayFor(timeoutMillisArg).then(async () => {
await subscriptionMap.forEach((subscriptionArg) => {
subscriptionArg.unsubscribe();
});
reactionResult.complete();
});
return reactionResult;
}
}