import * as plugins from './smartuniverse.plugins'; import { UniverseChannel } from './smartuniverse.classes.universechannel'; import { ClientUniverseChannel } from './smartuniverse.classes.clientuniversechannel'; import { ReactionResult } from './smartuniverse.classes.reactionresult'; import { UniverseMessage } from './smartuniverse.classes.universemessage'; import { ClientUniverseMessage } from './smartuniverse.classes.clientuniversemessage'; export interface IReactionRequestConstructorOptions { method: T['method']; } export interface ICombinatorPayload { /** * needed for tying responses to requests */ id: string; typedRequestPayload: { method: T['method'], request : T['request'], response: T['response'] }; } export class ReactionRequest { public method: T['method']; constructor(optionsArg: IReactionRequestConstructorOptions) { this.method = optionsArg.method; } public async fire(channelsArg: Array, timeoutMillisArg=60000) { const subscriptionMap = new plugins.lik.Objectmap(); const reactionResult = new ReactionResult(); const requestId = plugins.smartunique.shortId(); for (const channel of channelsArg) { subscriptionMap.add(channel.subscribe((messageArg: UniverseMessage> | ClientUniverseMessage>) => { if (messageArg.messageText === 'reactionResponse' && messageArg.payload.typedRequestPayload.method === this.method) { const payload: ICombinatorPayload = messageArg.payload; if (payload.id !== requestId) { return; } reactionResult.pushReactionResponse(payload.typedRequestPayload.response); } })); } plugins.smartdelay.delayFor(timeoutMillisArg).then(async () => { await subscriptionMap.forEach(subscriptionArg => { subscriptionArg.unsubscribe(); }); reactionResult.complete(); }); return reactionResult; } }