diff --git a/client/lib/CoreTab.ts b/client/lib/CoreTab.ts index 5a25b174e..95e551d97 100644 --- a/client/lib/CoreTab.ts +++ b/client/lib/CoreTab.ts @@ -144,18 +144,18 @@ export default class CoreTab implements IJsPathEventTarget { await this.commandQueue.runOutOfBand('Tab.registerFlowHandler', name, id, callsitePath); } - public async runFlowCommand( - commandFn: () => Promise, + public async runFlowCommand( + commandFn: () => Promise, exitState: IDomState | DomState | IDomStateAllFn, callsitePath: ISourceCodeLocation[], options?: IFlowCommandOptions - ): Promise { + ): Promise { if (typeof exitState === 'function') { exitState = { all: exitState }; } const flowCommand = await this.flowCommands.create(commandFn, exitState, callsitePath, options); - await flowCommand.run(); + return await flowCommand.run(); } public async shouldRetryFlowHandlers( diff --git a/client/lib/FlowCommand.ts b/client/lib/FlowCommand.ts index 060804b64..ddba00e31 100644 --- a/client/lib/FlowCommand.ts +++ b/client/lib/FlowCommand.ts @@ -7,7 +7,7 @@ import ISourceCodeLocation from '@ulixee/commons/interfaces/ISourceCodeLocation' import IDomState from '@ulixee/hero-interfaces/IDomState'; import IFlowCommandOptions from '@ulixee/hero-interfaces/IFlowCommandOptions'; -export default class FlowCommand implements IFlowCommand { +export default class FlowCommand implements IFlowCommand { public retryNumber = 0; public get isComplete(): Promise { @@ -29,10 +29,11 @@ export default class FlowCommand implements IFlowCommand { public isFlowStateChanged = false; private readonly exitHandler: DomStateHandler; + private lastResult: T; constructor( private readonly coreTab: CoreTab, - private runCommandsFn: () => Promise, + private runCommandsFn: () => Promise, exitState: IDomState, readonly id: number, readonly parent: FlowCommand, @@ -47,9 +48,11 @@ export default class FlowCommand implements IFlowCommand { } } - async run(): Promise { + async run(): Promise { // if we have previously tried this and it's still valid, break out - if (this.retryNumber > 0 && !!this.exitHandler && (await this.isComplete)) return; + if (this.retryNumber > 0 && !!this.exitHandler && (await this.isComplete)) { + return this.lastResult; + } // Retry until isComplete is satisfied, or we have retried a max number of times for (let count = 0; count < this.options.maxRetries; count += 1) { @@ -58,9 +61,9 @@ export default class FlowCommand implements IFlowCommand { this.isFlowStateChanged = false; // clear out any flow state changes this.retryNumber += count; // add to retry count because we might be nested this.setCommandState(); - await this.runCommandsFn(); + this.lastResult = await this.runCommandsFn(); - if (await this.isComplete) return; + if (await this.isComplete) return this.lastResult; if (this.isFlowStateChanged) continue; // if not complete, trigger flow handlers to retry (catch will trigger on its own) diff --git a/client/lib/FlowCommands.ts b/client/lib/FlowCommands.ts index 2b678ece6..4d2abea3d 100644 --- a/client/lib/FlowCommands.ts +++ b/client/lib/FlowCommands.ts @@ -5,7 +5,7 @@ import IDomState from '@ulixee/hero-interfaces/IDomState'; import IFlowCommandOptions from '@ulixee/hero-interfaces/IFlowCommandOptions'; export default class FlowCommands { - private readonly flowCommands: FlowCommand[] = []; + private readonly flowCommands: FlowCommand[] = []; public get runningFlowCommand(): FlowCommand { return this.flowCommands.find(x => x.isRunning); @@ -17,21 +17,21 @@ export default class FlowCommands { constructor(private readonly coreTab: CoreTab) {} - public async create( - commandFn: () => Promise, + public async create( + commandFn: () => Promise, exitState: IDomState, callsitePath: ISourceCodeLocation[], options: IFlowCommandOptions, - ): Promise { + ): Promise> { const id = this.flowCommands.length + 1; const parentFlow = this.runningFlowCommand; - let flowCommand: FlowCommand; + let flowCommand: FlowCommand; if (parentFlow && parentFlow.retryNumber > 0) { const callsiteJson = JSON.stringify(callsitePath); flowCommand = this.flowCommands.find( x => x.parentId === parentFlow.id && callsiteJson === JSON.stringify(x.callsitePath), - ); + ) as any; flowCommand.retryNumber += 1; return flowCommand; } else { diff --git a/client/lib/Tab.ts b/client/lib/Tab.ts index 1b56e3581..63fb046de 100644 --- a/client/lib/Tab.ts +++ b/client/lib/Tab.ts @@ -281,20 +281,20 @@ export default class Tab extends AwaitedEventTarget { await coreTab.registerFlowHandler(name, state, handlerFn, callsitePath); } - public async flowCommand( - commandFn: () => Promise, + public async triggerFlowHandlers(): Promise { + const coreTab = await this.#coreTabPromise; + await coreTab.triggerFlowHandlers(); + } + + public async flowCommand( + commandFn: () => Promise, exitState?: IDomState | DomState | IDomStateAllFn, options?: IFlowCommandOptions - ): Promise { + ): Promise { const callsitePath = scriptInstance.getScriptCallsite(); const coreTab = await this.#coreTabPromise; - await coreTab.runFlowCommand(commandFn, exitState, callsitePath, options); - } - - public async triggerFlowHandlers(): Promise { - const coreTab = await this.#coreTabPromise; - await coreTab.triggerFlowHandlers(); + return await coreTab.runFlowCommand(commandFn, exitState, callsitePath, options); } public waitForResource(