diff --git a/modules/conjoin_emitter.ts b/modules/conjoin_emitter.ts index 3fe7ca2..388b08c 100644 --- a/modules/conjoin_emitter.ts +++ b/modules/conjoin_emitter.ts @@ -16,6 +16,7 @@ import { CoreEmitter } from "modules/core_emitter.ts"; import { Emitter } from "modules/emitter.ts"; import { SeriesRunner } from "modules/runners/series.ts"; import { ConjoinQueue } from "modules/conjoin_queue.ts"; +import { RelayRunner } from "modules/runners/relay.ts"; import * as helpers from "modules/helpers.ts"; export class ConjoinEmitter extends CoreEmitter @@ -136,10 +137,7 @@ export class ConjoinEmitter extends CoreEmitter return this.prevEvents; }; - if (this.prevEvents instanceof Promise) { - return Promise.resolve(this.prevEvents).then(next); - } - return next(); + return new RelayRunner().exec(this.prevEvents, next, { async: true }); } off(event: ConjoinEvents, handler?: EventHandler): void { diff --git a/modules/runners/dual.ts b/modules/runners/dual.ts index 10f5592..a8b7226 100644 --- a/modules/runners/dual.ts +++ b/modules/runners/dual.ts @@ -4,6 +4,7 @@ import type { } from "modules/types.ts"; import { SequenceRunner } from "modules/runners/sequence.ts"; +import { RelayRunner } from "modules/runners/relay.ts"; /** * Run a dual event handler. @@ -53,9 +54,6 @@ export class DualRunner { * @param args The arguments to pass to the dual handler. */ exec(result: any) { - if (result instanceof Promise) { - return Promise.resolve(result).then((res) => this.dualExec(res)); - } - return this.dualExec(result); + return new RelayRunner().exec(result, (p) => this.dualExec(p)); } } diff --git a/modules/runners/relay.ts b/modules/runners/relay.ts new file mode 100644 index 0000000..07851b1 --- /dev/null +++ b/modules/runners/relay.ts @@ -0,0 +1,30 @@ +import type { EventHandler } from "modules/types.ts"; + +/** Options to RelayRunner */ +export type RelayRunnerOptions = { + /** + * If the prev handler is a promise, it will await for it before executing the next handler. + * @default false + */ + async: boolean; +}; + +/** Handle how to run before and after handler. */ +export class RelayRunner { + /** + * Execute the handler. + * @param prev The result of the previous handler. + * @param next The next handler. + * @param options The options to run the next handler. + */ + exec( + prev: any, + next: T, + options?: Partial, + ): Promise> | ReturnType { + if (prev instanceof Promise) { + return Promise.resolve(prev).then((res) => next(res)); + } + return next(prev); + } +} diff --git a/modules/runners/sequence.ts b/modules/runners/sequence.ts index f048ade..d16beec 100644 --- a/modules/runners/sequence.ts +++ b/modules/runners/sequence.ts @@ -1,6 +1,7 @@ import type { GeneralEventHandlerSignature } from "modules/types.ts"; import { SingleRunner } from "modules/runners/single.ts"; +import { RelayRunner } from "modules/runners/relay.ts"; /** * Run handlers in sequence. @@ -26,18 +27,15 @@ export class SequenceRunner< exec( args: Parameters, index: number = 0, - ): void | Promise { + ): ReturnType | Promise> | void { const profile = this.handlers[index]; if (!profile) return; const result = new SingleRunner(profile).exec(args) as any; - /** - * Wait for the handler to finish before moving to the next handler. - */ - if (profile.options?.async || result instanceof Promise) { - return Promise.resolve(result).then(() => this.exec(args, index + 1)); - } - return this.exec(args, index + 1); + return new RelayRunner().exec( + result, + () => this.exec(args, index + 1), + ) as any; } } diff --git a/modules/runners/series.ts b/modules/runners/series.ts index 489da3c..79e4174 100644 --- a/modules/runners/series.ts +++ b/modules/runners/series.ts @@ -1,6 +1,7 @@ import type { EventName, RegisteredHandlers } from "modules/types.ts"; import { StepRunner } from "modules/runners/step.ts"; +import { RelayRunner } from "modules/runners/relay.ts"; /** * Run handlers each in series. @@ -24,9 +25,9 @@ export class SeriesRunner { if (!key) return; const step = new StepRunner(this.handlers).exec(key); - if (step instanceof Promise) { - return Promise.resolve(step).then(() => this.exec(series, idx + 1)); - } - return this.exec(series, idx + 1); + return new RelayRunner().exec( + step, + () => this.exec(series, idx + 1), + ) as any; } } diff --git a/modules/runners/step.ts b/modules/runners/step.ts index 574a7dc..c5ad15d 100644 --- a/modules/runners/step.ts +++ b/modules/runners/step.ts @@ -9,6 +9,7 @@ import type { import { DualRunner } from "modules/runners/dual.ts"; import { SingleRunner } from "modules/runners/single.ts"; import { SequenceRunner } from "modules/runners/sequence.ts"; +import { RelayRunner } from "modules/runners/relay.ts"; import * as helpers from "modules/helpers.ts"; /** @@ -51,17 +52,13 @@ export class StepRunner { const next = (result: any) => { const dualResult = new DualRunner(duals).exec(!!result); - if (dualResult instanceof Promise) { - return dualResult.then(() => - this.execByIndex(handlers, duals, args, idx + 1) - ); - } + return new RelayRunner().exec( + dualResult, + () => this.execByIndex(handlers, duals, args, idx + 1), + ); }; - if (handler.options?.async) { - return Promise.resolve(result).then(() => next(result)); - } - return next(result); + return new RelayRunner().exec(result, next) as any; } /**