From 260d52af35698b4d99190691d1ff90153e024666 Mon Sep 17 00:00:00 2001 From: peaBerberian Date: Sun, 19 Aug 2018 14:03:02 +0200 Subject: [PATCH] fix(switchMap): stop listening to a synchronous inner-obervable when unsubscribed --- spec/operators/switchMap-spec.ts | 29 +++++++++++++++++++++++++++-- src/internal/operators/switchMap.ts | 4 +++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/spec/operators/switchMap-spec.ts b/spec/operators/switchMap-spec.ts index 4eabe0ae3d..779b4ebf55 100644 --- a/spec/operators/switchMap-spec.ts +++ b/spec/operators/switchMap-spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing'; -import { switchMap, mergeMap, map } from 'rxjs/operators'; -import { of, Observable } from 'rxjs'; +import { switchMap, mergeMap, map, takeWhile } from 'rxjs/operators'; +import { concat, defer, of, Observable } from 'rxjs'; declare function asDiagram(arg: string): Function; @@ -169,6 +169,31 @@ describe('switchMap', () => { expectSubscriptions(e1.subscriptions).toBe(e1subs); }); + it('should stop listening to a synchronous observable when unsubscribed', () => { + const sideEffects: number[] = []; + const synchronousObservable = concat( + defer(() => { + sideEffects.push(1); + return of(1); + }), + defer(() => { + sideEffects.push(2); + return of(2); + }), + defer(() => { + sideEffects.push(3); + return of(3); + }) + ); + + of(null).pipe( + switchMap(() => synchronousObservable), + takeWhile((x) => x != 2) // unsubscribe at the second side-effect + ).subscribe(() => { /* noop */ }); + + expect(sideEffects).to.deep.equal([1, 2]); + }); + it('should switch inner cold observables, inner never completes', () => { const x = cold( '--a--b--c--d--e--| '); const xsubs = ' ^ ! '; diff --git a/src/internal/operators/switchMap.ts b/src/internal/operators/switchMap.ts index 136fae3d43..ee83978c08 100644 --- a/src/internal/operators/switchMap.ts +++ b/src/internal/operators/switchMap.ts @@ -113,7 +113,9 @@ class SwitchMapSubscriber extends OuterSubscriber { if (innerSubscription) { innerSubscription.unsubscribe(); } - this.add(this.innerSubscription = subscribeToResult(this, result, value, index)); + const innerSubscriber = new InnerSubscriber(this, undefined, undefined); + this.add(innerSubscriber); + this.innerSubscription = subscribeToResult(this, result, value, index, innerSubscriber); } protected _complete(): void {