From 6ba60f100ba3defece25d1bd86a66759c3c77251 Mon Sep 17 00:00:00 2001 From: Maxim Kucherov Date: Tue, 6 Sep 2022 12:33:23 +0300 Subject: [PATCH] Fix TimeoutScheduler disposing --- src/core/timeoutScheduler.ts | 13 +++++++++---- tests/core/timeoutScheduler.test.ts | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/core/timeoutScheduler.ts b/src/core/timeoutScheduler.ts index 33a445a..b3ea7a5 100644 --- a/src/core/timeoutScheduler.ts +++ b/src/core/timeoutScheduler.ts @@ -2,7 +2,7 @@ import type { Disposable } from '../common'; export class TimeoutScheduler implements Disposable { private counterExpirationWatcherId: ReturnType | undefined; - private actionWatcherId: ReturnType | undefined; + private actionWatchers = new Set>(); private _counter = 0; constructor( @@ -22,8 +22,7 @@ export class TimeoutScheduler implements Disposable { if (this.counterExpirationWatcherId) clearTimeout(this.counterExpirationWatcherId); - if (this.actionWatcherId) - clearTimeout(this.actionWatcherId); + this.actionWatchers.forEach(watcher => clearTimeout(watcher)); } setTimeout(action: () => void) { @@ -32,7 +31,13 @@ export class TimeoutScheduler implements Disposable { const timeoutIndex = Math.min(this.counter, this.timeouts.length - 1); const timeout = this.timeouts[timeoutIndex]; - this.actionWatcherId = setTimeout(action, timeout); + + const watcherId = setTimeout(() => { + this.actionWatchers.delete(watcherId); + clearTimeout(watcherId); + action(); + }, timeout); + this.actionWatchers.add(watcherId); this.counter++; } diff --git a/tests/core/timeoutScheduler.test.ts b/tests/core/timeoutScheduler.test.ts index 895abab..b788bc1 100644 --- a/tests/core/timeoutScheduler.test.ts +++ b/tests/core/timeoutScheduler.test.ts @@ -4,6 +4,10 @@ import { TimeoutScheduler } from '../../src/core'; describe('TimeoutScheduler', () => { let scheduler: TimeoutScheduler; + beforeEach(() => { + jest.useRealTimers(); + }); + afterEach(() => { scheduler.dispose(); }); @@ -76,4 +80,17 @@ describe('TimeoutScheduler', () => { expect(counter).toEqual(4); expect(scheduler.counter).toEqual(1); }); + + test('stops all scheduled tasks on dispose', () => { + jest.useFakeTimers(); + const action = jest.fn(); + scheduler = new TimeoutScheduler([10000, 10000]); + + scheduler.setTimeout(action); + scheduler.setTimeout(action); + scheduler.setTimeout(action); + expect(jest.getTimerCount()).toBe(3); + scheduler.dispose(); + expect(jest.getTimerCount()).toBe(0); + }); });