From 57ad5c5643668aeaf15e0449250558dccf67013f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Stanimirovi=C4=87?= Date: Wed, 13 Nov 2024 22:20:57 +0100 Subject: [PATCH] feat(signals): rename `rxMethod.unsubscribe` to `destroy` (#4584) BREAKING CHANGES: The `unsubscribe` method from `rxMethod` is renamed to `destroy`. BEFORE: const logNumber = rxMethod(tap(console.log)); const num1Ref = logNumber(interval(1_000)); const num2Ref = logNumber(interval(2_000)); // destroy `num1Ref` after 2 seconds setTimeout(() => num1Ref.unsubscribe(), 2_000); // destroy all reactive method refs after 5 seconds setTimeout(() => logNumber.unsubscribe(), 5_000); AFTER: const logNumber = rxMethod(tap(console.log)); const num1Ref = logNumber(interval(1_000)); const num2Ref = logNumber(interval(2_000)); // destroy `num1Ref` after 2 seconds setTimeout(() => num1Ref.destroy(), 2_000); // destroy all reactive method refs after 5 seconds setTimeout(() => logNumber.destroy(), 5_000); --- .../rxjs-interop/spec/rx-method.spec.ts | 10 ++++---- modules/signals/rxjs-interop/src/rx-method.ts | 23 +++++++++++-------- .../content/guide/signals/rxjs-integration.md | 18 +++++++-------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/modules/signals/rxjs-interop/spec/rx-method.spec.ts b/modules/signals/rxjs-interop/spec/rx-method.spec.ts index cd63dba3e5..e87cd67172 100644 --- a/modules/signals/rxjs-interop/spec/rx-method.spec.ts +++ b/modules/signals/rxjs-interop/spec/rx-method.spec.ts @@ -96,8 +96,8 @@ describe('rxMethod', () => { const subject$ = new Subject(); const sig = signal(0); - const sub1 = method(subject$); - const sub2 = method(sig); + const ref1 = method(subject$); + const ref2 = method(sig); expect(results).toEqual([]); subject$.next(1); @@ -105,13 +105,13 @@ describe('rxMethod', () => { TestBed.flushEffects(); expect(results).toEqual([1, 1]); - sub1.unsubscribe(); + ref1.destroy(); subject$.next(2); sig.set(2); TestBed.flushEffects(); expect(results).toEqual([1, 1, 2]); - sub2.unsubscribe(); + ref2.destroy(); sig.set(3); TestBed.flushEffects(); expect(results).toEqual([1, 1, 2]); @@ -138,7 +138,7 @@ describe('rxMethod', () => { method(1); expect(results).toEqual([1, 1, 1]); - method.unsubscribe(); + method.destroy(); expect(destroyed).toBe(true); subject1$.next(2); diff --git a/modules/signals/rxjs-interop/src/rx-method.ts b/modules/signals/rxjs-interop/src/rx-method.ts index 5d93ff877f..4d31ac81ba 100644 --- a/modules/signals/rxjs-interop/src/rx-method.ts +++ b/modules/signals/rxjs-interop/src/rx-method.ts @@ -8,13 +8,17 @@ import { Signal, untracked, } from '@angular/core'; -import { isObservable, noop, Observable, Subject, Unsubscribable } from 'rxjs'; +import { isObservable, noop, Observable, Subject } from 'rxjs'; + +type RxMethodRef = { + destroy: () => void; +}; type RxMethod = (( input: Input | Signal | Observable, config?: { injector?: Injector } -) => Unsubscribable) & - Unsubscribable; +) => RxMethodRef) & + RxMethodRef; export function rxMethod( generator: (source$: Observable) => Observable, @@ -32,10 +36,10 @@ export function rxMethod( const rxMethodFn = ( input: Input | Signal | Observable, config?: { injector?: Injector } - ) => { + ): RxMethodRef => { if (isStatic(input)) { source$.next(input); - return { unsubscribe: noop }; + return { destroy: noop }; } const instanceInjector = @@ -49,10 +53,9 @@ export function rxMethod( }, { injector: instanceInjector } ); - const instanceSub = { unsubscribe: () => watcher.destroy() }; - sourceSub.add(instanceSub); + sourceSub.add({ unsubscribe: () => watcher.destroy() }); - return instanceSub; + return watcher; } const instanceSub = input.subscribe((value) => source$.next(value)); @@ -64,9 +67,9 @@ export function rxMethod( .onDestroy(() => instanceSub.unsubscribe()); } - return instanceSub; + return { destroy: () => instanceSub.unsubscribe() }; }; - rxMethodFn.unsubscribe = sourceSub.unsubscribe.bind(sourceSub); + rxMethodFn.destroy = sourceSub.unsubscribe.bind(sourceSub); return rxMethodFn; } diff --git a/projects/ngrx.io/content/guide/signals/rxjs-integration.md b/projects/ngrx.io/content/guide/signals/rxjs-integration.md index efce6d3196..07dfdc05e1 100644 --- a/projects/ngrx.io/content/guide/signals/rxjs-integration.md +++ b/projects/ngrx.io/content/guide/signals/rxjs-integration.md @@ -247,7 +247,7 @@ If the injector is not provided when calling the reactive method outside of curr ### Manual Cleanup -If a reactive method needs to be cleaned up before the injector is destroyed, manual cleanup can be performed by calling the `unsubscribe` method. +If a reactive method needs to be cleaned up before the injector is destroyed, manual cleanup can be performed by calling the `destroy` method. ```ts import { Component, OnInit } from '@angular/core'; @@ -266,15 +266,15 @@ export class NumbersComponent implements OnInit { this.logNumber(num2$); setTimeout(() => { - // 👇 Clean up all reactive method subscriptions after 3 seconds. - this.logNumber.unsubscribe(); + // 👇 Destroy the reactive method after 3 seconds. + this.logNumber.destroy(); }, 3_000); } } ``` -When invoked, the reactive method returns a subscription. -Using this subscription allows manual unsubscribing from a specific call, preserving the activity of other reactive method calls until the corresponding injector is destroyed. +When invoked, the reactive method returns the object with the `destroy` method. +This allows manual cleanup of a specific call, preserving the activity of other reactive method calls until the corresponding injector is destroyed. ```ts import { Component, OnInit } from '@angular/core'; @@ -289,12 +289,12 @@ export class NumbersComponent implements OnInit { const num1$ = interval(500); const num2$ = interval(1_000); - const num1Sub = this.logNumber(num1$); - this.logNumber(num2$); + const num1Ref = this.logNumber(num1$); + const num2Ref = this.logNumber(num2$); setTimeout(() => { - // 👇 Clean up the first reactive method subscription after 2 seconds. - num1Sub.unsubscribe(); + // 👇 Destroy the first reactive method call after 2 seconds. + num1Ref.destroy(); }, 2_000); } }