diff --git a/spec/schedulers/AsapScheduler-spec.ts b/spec/schedulers/AsapScheduler-spec.ts index 56a2ff7609..5f28c81d75 100644 --- a/spec/schedulers/AsapScheduler-spec.ts +++ b/spec/schedulers/AsapScheduler-spec.ts @@ -115,6 +115,28 @@ describe('Scheduler.asap', () => { sandbox.restore(); }); + it('should not pass setImmediate ids to clearInterval when rescheduling with a delay', (done) => { + const sandbox = sinon.createSandbox(); + const setImmediateSpy = sandbox.spy(immediateProvider, 'setImmediate'); + const clearIntervalSpy = sandbox.spy(intervalProvider, 'clearInterval'); + const setIntervalSpy = sandbox.spy(intervalProvider, 'setInterval'); + + asap.schedule(function () { + try { + const immediateId = setImmediateSpy.getCall(0).returnValue; + this.schedule(undefined, 20); + expect(clearIntervalSpy).to.have.not.been.calledWith(immediateId); + expect(setIntervalSpy).to.have.been.calledOnce; + this.unsubscribe(); + sandbox.restore(); + done(); + } catch (error) { + sandbox.restore(); + done(error); + } + }, 0); + }); + it('should schedule an action to happen later', (done) => { let actionHappened = false; asap.schedule(() => { diff --git a/src/internal/scheduler/AsapAction.ts b/src/internal/scheduler/AsapAction.ts index 178f677e90..eb9164ec21 100644 --- a/src/internal/scheduler/AsapAction.ts +++ b/src/internal/scheduler/AsapAction.ts @@ -23,10 +23,11 @@ export class AsapAction extends AsyncAction { } protected recycleAsyncId(scheduler: AsapScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined { - // If delay exists and is greater than 0, or if the delay is null (the - // action wasn't rescheduled) but was originally scheduled as an async - // action, then recycle as an async action. - if (delay != null ? delay > 0 : this.delay > 0) { + // Only recycle as an interval action when this action was itself scheduled + // with setInterval. Immediate handles share the number space of timer IDs, + // so passing them to clearInterval can cancel unrelated intervals + // (for example timer(0, period, asapScheduler) rescheduling after the first tick). + if (this.delay > 0) { return super.recycleAsyncId(scheduler, id, delay); } // If the scheduler queue has no remaining actions with the same async id,