From c19a986858f9931e4f6e8cce68da9da6bf2fe697 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Jul 2020 12:19:18 +0300 Subject: [PATCH 1/5] feat: add a subscription service --- .../packages/core/src/lib/services/index.ts | 1 + .../src/lib/services/subscription.service.ts | 50 ++++++++++ .../lib/tests/subscription.service.spec.ts | 95 +++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/services/subscription.service.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index 064dcbd35e..e5e5286710 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -11,4 +11,5 @@ export * from './profile.service'; export * from './rest.service'; export * from './routes.service'; export * from './session-state.service'; +export * from './subscription.service'; export * from './track-by.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts new file mode 100644 index 0000000000..81739d10ae --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts @@ -0,0 +1,50 @@ +import { Injectable } from '@angular/core'; +import type { OnDestroy } from '@angular/core'; +import { Subscription } from 'rxjs'; +import type { Observable, PartialObserver } from 'rxjs'; + +@Injectable() +export class SubscriptionService implements OnDestroy { + private subscription = new Subscription(); + + get isClosed() { + return this.subscription.closed; + } + + ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + reset() { + this.subscription.unsubscribe(); + this.subscription = new Subscription(); + } + + subscribe( + source$: Observable, + next?: (value: T) => void, + error?: (error: any) => void, + ): Subscription; + subscribe(source$: Observable, observer?: PartialObserver): Subscription; + subscribe( + source$: Observable, + nextOrObserver?: PartialObserver | Next, + error?: (error: any) => void, + ): Subscription { + const subscription = source$.subscribe(nextOrObserver as Next, error); + this.subscription.add(subscription); + return subscription; + } + + unsubscribe(subscription: Subscription | undefined | null) { + if (!subscription) return; + this.subscription.remove(subscription); + subscription.unsubscribe(); + } + + unsubscribeAll() { + this.subscription.unsubscribe(); + } +} + +type Next = (value: T) => void; diff --git a/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts new file mode 100644 index 0000000000..95df285fb9 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts @@ -0,0 +1,95 @@ +import { of, Subscription, timer } from 'rxjs'; +import { SubscriptionService } from '../services/subscription.service'; + +describe('SubscriptionService', () => { + let service: SubscriptionService; + + beforeEach(() => { + service = new SubscriptionService(); + }); + + afterEach(() => { + service['subscription'].unsubscribe(); + }); + + describe('#subscribe', () => { + it('should subscribe to given observable with next and error functions and return the Subscription instance', () => { + const next = jest.fn(); + const error = jest.fn(); + const subscription = service.subscribe(of(null), next, error); + expect(subscription).toBeInstanceOf(Subscription); + expect(next).toHaveBeenCalledWith(null); + expect(next).toHaveBeenCalledTimes(1); + expect(error).not.toHaveBeenCalled(); + }); + + it('should subscribe to given observable with observer and return the Subscription instance', () => { + const observer = { next: jest.fn(), complete: jest.fn() }; + const subscription = service.subscribe(of(null), observer); + expect(subscription).toBeInstanceOf(Subscription); + expect(observer.next).toHaveBeenCalledWith(null); + expect(observer.next).toHaveBeenCalledTimes(1); + expect(observer.complete).toHaveBeenCalledTimes(1); + }); + }); + + describe('#isClosed', () => { + it('should return true if subscriptions are alive and false if not', () => { + service.subscribe(timer(1000), () => {}); + expect(service.isClosed).toBe(false); + + service['subscription'].unsubscribe(); + expect(service.isClosed).toBe(true); + }); + }); + + describe('#unsubscribeAll', () => { + it('should close all subscriptions and the parent subscription', () => { + const sub1 = service.subscribe(timer(1000), () => {}); + const sub2 = service.subscribe(timer(1000), () => {}); + + expect(sub1.closed).toBe(false); + expect(sub2.closed).toBe(false); + expect(service.isClosed).toBe(false); + + service.unsubscribeAll(); + + expect(sub1.closed).toBe(true); + expect(sub2.closed).toBe(true); + expect(service.isClosed).toBe(true); + }); + }); + + describe('#reset', () => { + it('should close all subscriptions but not the parent subscription', () => { + const sub1 = service.subscribe(timer(1000), () => {}); + const sub2 = service.subscribe(timer(1000), () => {}); + + expect(sub1.closed).toBe(false); + expect(sub2.closed).toBe(false); + expect(service.isClosed).toBe(false); + + service.reset(); + + expect(sub1.closed).toBe(true); + expect(sub2.closed).toBe(true); + expect(service.isClosed).toBe(false); + }); + }); + + describe('#unsubscribe', () => { + it('should unsubscribe from given subscription only', () => { + const sub1 = service.subscribe(timer(1000), () => {}); + const sub2 = service.subscribe(timer(1000), () => {}); + expect(service.isClosed).toBe(false); + + service.unsubscribe(sub1); + expect(sub1.closed).toBe(true); + expect(service.isClosed).toBe(false); + + service.unsubscribe(sub2); + expect(sub2.closed).toBe(true); + expect(service.isClosed).toBe(false); + }); + }); +}); From 8d4180419fccfddd5c13c1fe9adffde200928a2e Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Jul 2020 12:54:14 +0300 Subject: [PATCH 2/5] feat: add removeOne method to SubscriptionService --- .../src/lib/services/subscription.service.ts | 16 +++++++++------ .../lib/tests/subscription.service.spec.ts | 20 ++++++++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts index 81739d10ae..eadec95b61 100644 --- a/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts @@ -15,6 +15,11 @@ export class SubscriptionService implements OnDestroy { this.subscription.unsubscribe(); } + removeOne(subscription: Subscription | undefined | null) { + if (!subscription) return; + this.subscription.remove(subscription); + } + reset() { this.subscription.unsubscribe(); this.subscription = new Subscription(); @@ -36,15 +41,14 @@ export class SubscriptionService implements OnDestroy { return subscription; } - unsubscribe(subscription: Subscription | undefined | null) { - if (!subscription) return; - this.subscription.remove(subscription); - subscription.unsubscribe(); - } - unsubscribeAll() { this.subscription.unsubscribe(); } + + unsubscribeOne(subscription: Subscription | undefined | null) { + this.removeOne(subscription); + subscription.unsubscribe(); + } } type Next = (value: T) => void; diff --git a/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts index 95df285fb9..c803455083 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts @@ -77,19 +77,33 @@ describe('SubscriptionService', () => { }); }); - describe('#unsubscribe', () => { + describe('#unsubscribeOne', () => { it('should unsubscribe from given subscription only', () => { const sub1 = service.subscribe(timer(1000), () => {}); const sub2 = service.subscribe(timer(1000), () => {}); expect(service.isClosed).toBe(false); - service.unsubscribe(sub1); + service.unsubscribeOne(sub1); expect(sub1.closed).toBe(true); expect(service.isClosed).toBe(false); - service.unsubscribe(sub2); + service.unsubscribeOne(sub2); expect(sub2.closed).toBe(true); expect(service.isClosed).toBe(false); }); }); + + describe('#removeOne', () => { + it('should remove given subscription from list of subscriptions', () => { + const sub1 = service.subscribe(timer(1000), () => {}); + const sub2 = service.subscribe(timer(1000), () => {}); + expect(service.isClosed).toBe(false); + + service.removeOne(sub1); + expect(sub1.closed).toBe(false); + expect(service.isClosed).toBe(false); + + sub1.unsubscribe(); + }); + }); }); From 6f1a42373dc03c01a281f78bf2167765ec707c85 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Jul 2020 13:04:27 +0300 Subject: [PATCH 3/5] docs: explain how the subscription service works --- docs/en/UI/Angular/Subscription-Service.md | 203 +++++++++++++++++++++ docs/en/UI/Angular/Track-By-Service.md | 2 +- docs/en/docs-nav.json | 4 + 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 docs/en/UI/Angular/Subscription-Service.md diff --git a/docs/en/UI/Angular/Subscription-Service.md b/docs/en/UI/Angular/Subscription-Service.md new file mode 100644 index 0000000000..b92cd26c59 --- /dev/null +++ b/docs/en/UI/Angular/Subscription-Service.md @@ -0,0 +1,203 @@ +# Easy Unsubscription for Your Observables + +`SubscriptionService` is a utility service to provide an easy unsubscription from RxJS observables in Angular components and directives. Please see [why you should unsubscribe from observables on instance destruction](https://angular.io/guide/lifecycle-hooks#cleaning-up-on-instance-destruction). + +## Getting Started + +You have to provide the `SubscriptionService` at component or directive level, because it is **not provided in root** and it works in sync with component/directive lifecycle. Only after then you can inject and start using it. + +```js +import { SubscriptionService } from '@abp/ng.core'; + +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent { + count$ = interval(1000); + + constructor(private subscription: SubscriptionService) { + this.subscription.subscribe(this.count$, console.log); + } +} +``` + +The values emitted by the `count$` will be logged until the component is destroyed. You will not have to `unsubscribe` manually. + +> Please do not try to use a singleton `SubscriptionService`. It simply will not work. + +## Usage + +### How to Subscribe to Observables + +You can pass a `next` function and an `error` function. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + const source$ = interval(1000); + const nextFn = value => console.log(value * 2); + const errorFn = error => { + console.error(error); + return of(null); + }; + + this.subscription.subscribe(source$, nextFn, errorFn); + } +} +``` + +Or, you can pass an observer. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + const source$ = interval(1000); + const observer = { + next: value => console.log(value * 2), + complete: () => console.log('DONE'), + }; + + this.subscription.subscribe(source$, observer); + } +} +``` + +Ths `subscribe` method returns the individual subscription, so that you may use it later on. Please see topics below for details. + +### How to Unsubscribe Before Instance Destruction + +There are two ways to do that. If you are not going to subscribe again, you may use the `unsubscribeAll` method. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + this.subscription.subscribe(interval(1000), console.log); + } + + onSomeEvent() { + this.subscription.unsubscribeAll(); + } +} +``` + +This will clear all subscriptions, but you will not be able to subscribe again. If you are planning to add another subscription, you may use the `reset` method instead. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + this.subscription.subscribe(interval(1000), console.log); + } + + onSomeEvent() { + this.subscription.reset(); + this.subscription.subscribe(interval(1000), console.warn); + } +} +``` + +### How to Unsubscribe From a Single Subscription + +Sometimes, you may need to unsubscribe from a particular subscription but leave others alive. In such a case, you may use the `unsubscribeOne` method. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + countSubscription: Subscription; + + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + this.countSubscription = this.subscription.subscribe( + interval(1000), + console.log + ); + } + + onSomeEvent() { + this.subscription.unsubscribeOne(this.countSubscription); + console.log(this.countSubscription.closed); // true + } +} +``` + +### How to Remove a Single Subscription From Tracked Subscriptions + +You may want to take control of a particular subscription. In such a case, you may use the `removeOne` method to remove it from tracked subscriptions. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + countSubscription: Subscription; + + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + this.countSubscription = this.subscription.subscribe( + interval(1000), + console.log + ); + } + + onSomeEvent() { + this.subscription.removeOne(this.countSubscription); + console.log(this.countSubscription.closed); // false + } +} +``` + +### How to Check If Unsubscribed From All + +Please use `isClosed` getter to check if `unsubscribeAll` was called before. + +```js +@Component({ + /* class metadata here */ + providers: [SubscriptionService], +}) +class DemoComponent implements OnInit { + constructor(private subscription: SubscriptionService) {} + + ngOnInit() { + this.subscription.subscribe(interval(1000), console.log); + } + + onSomeEvent() { + console.log(this.subscription.isClosed); // false + } +} +``` + +## What's Next? + +- [ListService](./List-Service.md) diff --git a/docs/en/UI/Angular/Track-By-Service.md b/docs/en/UI/Angular/Track-By-Service.md index 447cc4505a..050706accd 100644 --- a/docs/en/UI/Angular/Track-By-Service.md +++ b/docs/en/UI/Angular/Track-By-Service.md @@ -116,4 +116,4 @@ class DemoComponent { ## What's Next? -- [ListService](./List-Service.md) +- [SubscriptionService](./Subscription-Service.md) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index a6ab09dfee..85f1567406 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -434,6 +434,10 @@ "text": "TrackByService", "path": "UI/Angular/Track-By-Service.md" }, + { + "text": "SubscriptionService", + "path": "UI/Angular/Subscription-Service.md" + }, { "text": "ListService", "path": "UI/Angular/List-Service.md" From 0b2c9096cb088f5d5d9b90f870164546ae37315a Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Jul 2020 14:06:25 +0300 Subject: [PATCH 4/5] feat: rename subscription service methods --- .../src/lib/services/subscription.service.ts | 38 +++++++++---------- .../lib/tests/subscription.service.spec.ts | 34 ++++++++--------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts index eadec95b61..9296585d2a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/subscription.service.ts @@ -11,27 +11,13 @@ export class SubscriptionService implements OnDestroy { return this.subscription.closed; } - ngOnDestroy(): void { - this.subscription.unsubscribe(); - } - - removeOne(subscription: Subscription | undefined | null) { - if (!subscription) return; - this.subscription.remove(subscription); - } - - reset() { - this.subscription.unsubscribe(); - this.subscription = new Subscription(); - } - - subscribe( + addOne( source$: Observable, next?: (value: T) => void, error?: (error: any) => void, ): Subscription; - subscribe(source$: Observable, observer?: PartialObserver): Subscription; - subscribe( + addOne(source$: Observable, observer?: PartialObserver): Subscription; + addOne( source$: Observable, nextOrObserver?: PartialObserver | Next, error?: (error: any) => void, @@ -41,14 +27,28 @@ export class SubscriptionService implements OnDestroy { return subscription; } - unsubscribeAll() { + closeAll() { this.subscription.unsubscribe(); } - unsubscribeOne(subscription: Subscription | undefined | null) { + closeOne(subscription: Subscription | undefined | null) { this.removeOne(subscription); subscription.unsubscribe(); } + + ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + removeOne(subscription: Subscription | undefined | null) { + if (!subscription) return; + this.subscription.remove(subscription); + } + + reset() { + this.subscription.unsubscribe(); + this.subscription = new Subscription(); + } } type Next = (value: T) => void; diff --git a/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts index c803455083..d0c8c4754f 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/subscription.service.spec.ts @@ -12,11 +12,11 @@ describe('SubscriptionService', () => { service['subscription'].unsubscribe(); }); - describe('#subscribe', () => { + describe('#addOne', () => { it('should subscribe to given observable with next and error functions and return the Subscription instance', () => { const next = jest.fn(); const error = jest.fn(); - const subscription = service.subscribe(of(null), next, error); + const subscription = service.addOne(of(null), next, error); expect(subscription).toBeInstanceOf(Subscription); expect(next).toHaveBeenCalledWith(null); expect(next).toHaveBeenCalledTimes(1); @@ -25,7 +25,7 @@ describe('SubscriptionService', () => { it('should subscribe to given observable with observer and return the Subscription instance', () => { const observer = { next: jest.fn(), complete: jest.fn() }; - const subscription = service.subscribe(of(null), observer); + const subscription = service.addOne(of(null), observer); expect(subscription).toBeInstanceOf(Subscription); expect(observer.next).toHaveBeenCalledWith(null); expect(observer.next).toHaveBeenCalledTimes(1); @@ -35,7 +35,7 @@ describe('SubscriptionService', () => { describe('#isClosed', () => { it('should return true if subscriptions are alive and false if not', () => { - service.subscribe(timer(1000), () => {}); + service.addOne(timer(1000), () => {}); expect(service.isClosed).toBe(false); service['subscription'].unsubscribe(); @@ -43,16 +43,16 @@ describe('SubscriptionService', () => { }); }); - describe('#unsubscribeAll', () => { + describe('#closeAll', () => { it('should close all subscriptions and the parent subscription', () => { - const sub1 = service.subscribe(timer(1000), () => {}); - const sub2 = service.subscribe(timer(1000), () => {}); + const sub1 = service.addOne(timer(1000), () => {}); + const sub2 = service.addOne(timer(1000), () => {}); expect(sub1.closed).toBe(false); expect(sub2.closed).toBe(false); expect(service.isClosed).toBe(false); - service.unsubscribeAll(); + service.closeAll(); expect(sub1.closed).toBe(true); expect(sub2.closed).toBe(true); @@ -62,8 +62,8 @@ describe('SubscriptionService', () => { describe('#reset', () => { it('should close all subscriptions but not the parent subscription', () => { - const sub1 = service.subscribe(timer(1000), () => {}); - const sub2 = service.subscribe(timer(1000), () => {}); + const sub1 = service.addOne(timer(1000), () => {}); + const sub2 = service.addOne(timer(1000), () => {}); expect(sub1.closed).toBe(false); expect(sub2.closed).toBe(false); @@ -77,17 +77,17 @@ describe('SubscriptionService', () => { }); }); - describe('#unsubscribeOne', () => { + describe('#closeOne', () => { it('should unsubscribe from given subscription only', () => { - const sub1 = service.subscribe(timer(1000), () => {}); - const sub2 = service.subscribe(timer(1000), () => {}); + const sub1 = service.addOne(timer(1000), () => {}); + const sub2 = service.addOne(timer(1000), () => {}); expect(service.isClosed).toBe(false); - service.unsubscribeOne(sub1); + service.closeOne(sub1); expect(sub1.closed).toBe(true); expect(service.isClosed).toBe(false); - service.unsubscribeOne(sub2); + service.closeOne(sub2); expect(sub2.closed).toBe(true); expect(service.isClosed).toBe(false); }); @@ -95,8 +95,8 @@ describe('SubscriptionService', () => { describe('#removeOne', () => { it('should remove given subscription from list of subscriptions', () => { - const sub1 = service.subscribe(timer(1000), () => {}); - const sub2 = service.subscribe(timer(1000), () => {}); + const sub1 = service.addOne(timer(1000), () => {}); + const sub2 = service.addOne(timer(1000), () => {}); expect(service.isClosed).toBe(false); service.removeOne(sub1); From 03539decc414093183d4e0e543d312e28d88bbcb Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Jul 2020 14:06:49 +0300 Subject: [PATCH 5/5] docs: update subscription service method names --- docs/en/UI/Angular/Subscription-Service.md | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/en/UI/Angular/Subscription-Service.md b/docs/en/UI/Angular/Subscription-Service.md index b92cd26c59..5d920df96e 100644 --- a/docs/en/UI/Angular/Subscription-Service.md +++ b/docs/en/UI/Angular/Subscription-Service.md @@ -17,12 +17,12 @@ class DemoComponent { count$ = interval(1000); constructor(private subscription: SubscriptionService) { - this.subscription.subscribe(this.count$, console.log); + this.subscription.addOne(this.count$, console.log); } } ``` -The values emitted by the `count$` will be logged until the component is destroyed. You will not have to `unsubscribe` manually. +The values emitted by the `count$` will be logged until the component is destroyed. You will not have to unsubscribe manually. > Please do not try to use a singleton `SubscriptionService`. It simply will not work. @@ -48,7 +48,7 @@ class DemoComponent implements OnInit { return of(null); }; - this.subscription.subscribe(source$, nextFn, errorFn); + this.subscription.addOne(source$, nextFn, errorFn); } } ``` @@ -70,16 +70,16 @@ class DemoComponent implements OnInit { complete: () => console.log('DONE'), }; - this.subscription.subscribe(source$, observer); + this.subscription.addOne(source$, observer); } } ``` -Ths `subscribe` method returns the individual subscription, so that you may use it later on. Please see topics below for details. +The `addOne` method returns the individual subscription, so that you may use it later on. Please see topics below for details. ### How to Unsubscribe Before Instance Destruction -There are two ways to do that. If you are not going to subscribe again, you may use the `unsubscribeAll` method. +There are two ways to do that. If you are not going to subscribe again, you may use the `closeAll` method. ```js @Component({ @@ -90,11 +90,11 @@ class DemoComponent implements OnInit { constructor(private subscription: SubscriptionService) {} ngOnInit() { - this.subscription.subscribe(interval(1000), console.log); + this.subscription.addOne(interval(1000), console.log); } onSomeEvent() { - this.subscription.unsubscribeAll(); + this.subscription.closeAll(); } } ``` @@ -110,19 +110,19 @@ class DemoComponent implements OnInit { constructor(private subscription: SubscriptionService) {} ngOnInit() { - this.subscription.subscribe(interval(1000), console.log); + this.subscription.addOne(interval(1000), console.log); } onSomeEvent() { this.subscription.reset(); - this.subscription.subscribe(interval(1000), console.warn); + this.subscription.addOne(interval(1000), console.warn); } } ``` ### How to Unsubscribe From a Single Subscription -Sometimes, you may need to unsubscribe from a particular subscription but leave others alive. In such a case, you may use the `unsubscribeOne` method. +Sometimes, you may need to unsubscribe from a particular subscription but leave others alive. In such a case, you may use the `closeOne` method. ```js @Component({ @@ -135,14 +135,14 @@ class DemoComponent implements OnInit { constructor(private subscription: SubscriptionService) {} ngOnInit() { - this.countSubscription = this.subscription.subscribe( + this.countSubscription = this.subscription.addOne( interval(1000), console.log ); } onSomeEvent() { - this.subscription.unsubscribeOne(this.countSubscription); + this.subscription.closeOne(this.countSubscription); console.log(this.countSubscription.closed); // true } } @@ -163,7 +163,7 @@ class DemoComponent implements OnInit { constructor(private subscription: SubscriptionService) {} ngOnInit() { - this.countSubscription = this.subscription.subscribe( + this.countSubscription = this.subscription.addOne( interval(1000), console.log ); @@ -178,7 +178,7 @@ class DemoComponent implements OnInit { ### How to Check If Unsubscribed From All -Please use `isClosed` getter to check if `unsubscribeAll` was called before. +Please use `isClosed` getter to check if `closeAll` was called before. ```js @Component({ @@ -189,7 +189,7 @@ class DemoComponent implements OnInit { constructor(private subscription: SubscriptionService) {} ngOnInit() { - this.subscription.subscribe(interval(1000), console.log); + this.subscription.addOne(interval(1000), console.log); } onSomeEvent() {