From 202b79a2ff7f173dc382a93f878b6fc99c3c9f6d Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Mon, 14 Mar 2016 10:18:30 -0700 Subject: [PATCH] fix(Schedulers): ensure schedulers can be reused after error in execution --- spec/Scheduler-spec.ts | 21 +++++++++++++++++++++ src/scheduler/Action.ts | 1 + src/scheduler/FutureAction.ts | 6 ++++-- src/scheduler/QueueScheduler.ts | 4 ++++ src/scheduler/VirtualTimeScheduler.ts | 6 ++++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/spec/Scheduler-spec.ts b/spec/Scheduler-spec.ts index 0602e90cff..d220f35faf 100644 --- a/spec/Scheduler-spec.ts +++ b/spec/Scheduler-spec.ts @@ -34,4 +34,25 @@ describe('Scheduler.queue', () => { done(); }, 70); }); + + it('should be reusable after an error is thrown during execution', (done: DoneSignature) => { + const results = []; + + expect(() => { + Scheduler.queue.schedule(() => { + results.push(1); + }); + + Scheduler.queue.schedule(() => { + throw new Error('bad'); + }); + }).toThrow(new Error('bad')); + + setTimeout(() => { + Scheduler.queue.schedule(() => { + results.push(2); + done(); + }); + }, 0); + }); }); \ No newline at end of file diff --git a/src/scheduler/Action.ts b/src/scheduler/Action.ts index 9ac218ba80..e434c7f29f 100644 --- a/src/scheduler/Action.ts +++ b/src/scheduler/Action.ts @@ -8,4 +8,5 @@ export interface Action extends Subscription { schedule(state?: any, delay?: number): void; execute(): void; scheduler: Scheduler; + error: any; } \ No newline at end of file diff --git a/src/scheduler/FutureAction.ts b/src/scheduler/FutureAction.ts index fa778e0b01..7cd21456d9 100644 --- a/src/scheduler/FutureAction.ts +++ b/src/scheduler/FutureAction.ts @@ -8,6 +8,8 @@ export class FutureAction extends Subscription implements Action { public id: number; public state: T; public delay: number; + public error: any; + private pending: boolean = false; constructor(public scheduler: Scheduler, @@ -17,13 +19,13 @@ export class FutureAction extends Subscription implements Action { execute() { if (this.isUnsubscribed) { - throw new Error('How did did we execute a canceled Action?'); + this.error = new Error('executing a cancelled action'); } else { try { this.work(this.state); } catch (e) { this.unsubscribe(); - throw e; + this.error = e; } } } diff --git a/src/scheduler/QueueScheduler.ts b/src/scheduler/QueueScheduler.ts index c9e3a52efc..97829015f3 100644 --- a/src/scheduler/QueueScheduler.ts +++ b/src/scheduler/QueueScheduler.ts @@ -21,6 +21,10 @@ export class QueueScheduler implements Scheduler { const actions = this.actions; for (let action: QueueAction; action = actions.shift(); ) { action.execute(); + if (action.error) { + this.active = false; + throw action.error; + } } this.active = false; } diff --git a/src/scheduler/VirtualTimeScheduler.ts b/src/scheduler/VirtualTimeScheduler.ts index f1653475d3..af0af7899a 100644 --- a/src/scheduler/VirtualTimeScheduler.ts +++ b/src/scheduler/VirtualTimeScheduler.ts @@ -25,6 +25,11 @@ export class VirtualTimeScheduler implements Scheduler { this.frame = action.delay; if (this.frame <= maxFrames) { action.execute(); + if (action.error) { + actions.length = 0; + this.frame = 0; + throw action.error; + } } else { break; } @@ -65,6 +70,7 @@ class VirtualAction extends Subscription implements Action { state: T; delay: number; calls = 0; + error: any; constructor(public scheduler: VirtualTimeScheduler, public work: (x?: T) => Subscription | void,