diff --git a/libs/state/effects/src/lib/effects.service.ts b/libs/state/effects/src/lib/effects.service.ts index daf002bc4..04cc14d8c 100644 --- a/libs/state/effects/src/lib/effects.service.ts +++ b/libs/state/effects/src/lib/effects.service.ts @@ -1,10 +1,5 @@ -import { - DestroyRef, - ErrorHandler, - inject, - Injectable, - Optional, -} from '@angular/core'; +import { DestroyRef, ErrorHandler, inject, Injectable } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { EMPTY, from, @@ -18,14 +13,14 @@ import { import { catchError, filter, - mapTo, + map, mergeAll, share, takeUntil, tap, } from 'rxjs/operators'; import { DestroyProp, OnDestroy$ } from './model'; -import { toHook, untilDestroyed } from './utils'; +import { toHook } from './utils'; /** * @deprecated - use rxEffects instead @@ -72,17 +67,9 @@ import { toHook, untilDestroyed } from './utils'; */ @Injectable() export class RxEffects implements OnDestroy$ { - constructor( - @Optional() - private readonly errorHandler: ErrorHandler | null, - ) { - inject(DestroyRef).onDestroy(() => { - this._hooks$.next({ destroy: true }); - this.subscription.unsubscribe(); - }); - } - private static nextId = 0; + private readonly destroyRef = inject(DestroyRef); + private readonly errorHandler = inject(ErrorHandler, { optional: true }); readonly _hooks$ = new Subject(); private readonly observables$ = new Subject>(); // we have to use publish here to make it hot (composition happens without subscriber) @@ -91,6 +78,13 @@ export class RxEffects implements OnDestroy$ { onDestroy$: Observable = this._hooks$.pipe(toHook('destroy')); private readonly destroyers: Record> = {}; + constructor() { + this.destroyRef.onDestroy(() => { + this._hooks$.next({ destroy: true }); + this.subscription.unsubscribe(); + }); + } + /** * Performs a side-effect whenever a source observable emits, and handles its subscription. * @@ -171,7 +165,10 @@ export class RxEffects implements OnDestroy$ { } const effectId = RxEffects.nextId++; const destroy$ = (this.destroyers[effectId] = new Subject()); - const applyBehavior = pipe(mapTo(effectId), takeUntil(destroy$)); + const applyBehavior = pipe( + map(() => effectId), + takeUntil(destroy$), + ); if (fnOrObj != null) { this.observables$.next( from(obsOrSub).pipe( @@ -233,7 +230,7 @@ export class RxEffects implements OnDestroy$ { untilEffect(effectId: number) { return (source: Observable) => source.pipe( - untilDestroyed(this), + takeUntilDestroyed(this.destroyRef), takeUntil(this.effects$.pipe(filter((eId) => eId === effectId))), ); } diff --git a/libs/state/effects/src/lib/utils.ts b/libs/state/effects/src/lib/utils.ts index 7735017ba..70e87eef7 100644 --- a/libs/state/effects/src/lib/utils.ts +++ b/libs/state/effects/src/lib/utils.ts @@ -1,9 +1,9 @@ -import { MonoTypeOperatorFunction, Observable } from 'rxjs'; -import { filter, map, shareReplay, take, takeUntil } from 'rxjs/operators'; -import { HookProps, OnDestroy$, SingleShotProps } from './model'; +import { Observable } from 'rxjs'; +import { filter, map, shareReplay, take } from 'rxjs/operators'; +import { HookProps, SingleShotProps } from './model'; export function isSingleShotHookNameGuard( - name: unknown + name: unknown, ): name is keyof SingleShotProps { return !!name && typeof name === 'string' && name !== ''; } @@ -16,7 +16,7 @@ const singleShotOperators = (o$: Observable): Observable => o$.pipe( filter((v) => v === true), take(1), - shareReplay() + shareReplay(), ); /** @@ -32,19 +32,6 @@ export function toHook(name: H) { return (o$: Observable): Observable => o$.pipe( map((p) => p[name]), - operators + operators, ); } - -/** - * This operator can be used to take instances that implements `OnDestroy$` and unsubscribes from the given Observable when the instances - * `onDestroy$` Observable emits. - * - * @param instanceWithLifecycle - */ -export function untilDestroyed( - instanceWithLifecycle: OnDestroy$ -): MonoTypeOperatorFunction { - return (source) => - source.pipe(takeUntil(instanceWithLifecycle.onDestroy$)); -}