From 857f8c6cae953d17970e0e8bbd5939d7446a8bfa Mon Sep 17 00:00:00 2001 From: Denis Platonov Date: Sat, 18 Mar 2023 12:59:28 +0300 Subject: [PATCH] feature: add flipFLag rxjs operator function --- .../flip-flag-on-finalize.operator.spec.ts | 31 +++++++++++++++++++ .../flip-flag-on-finalize.operator.ts | 17 ++++++++++ 2 files changed, 48 insertions(+) create mode 100644 packages/rxjs/src/operators/flip-flag-on-finalize.operator.spec.ts create mode 100644 packages/rxjs/src/operators/flip-flag-on-finalize.operator.ts diff --git a/packages/rxjs/src/operators/flip-flag-on-finalize.operator.spec.ts b/packages/rxjs/src/operators/flip-flag-on-finalize.operator.spec.ts new file mode 100644 index 0000000..e987854 --- /dev/null +++ b/packages/rxjs/src/operators/flip-flag-on-finalize.operator.spec.ts @@ -0,0 +1,31 @@ +import { BehaviorSubject, of, throwError } from 'rxjs'; +import { delay } from 'rxjs/operators'; +import { flipFlagOnFinalize } from './flip-flag-on-finalize.operator'; + +describe('flip-flag-on-finalize.operator.ts', () => { + let isLoading$: BehaviorSubject; + + beforeEach(() => { + isLoading$ = new BehaviorSubject(false); + }); + + it('should set loading state to false after source completes', () => { + of('test') + .pipe(flipFlagOnFinalize(isLoading$)) + .subscribe({ + complete: () => { + expect(isLoading$.getValue()).toBe(false); + } + }); + }); + + it('should set loading state to false after source errors', () => { + throwError('error') + .pipe(delay(10), flipFlagOnFinalize(isLoading$), delay(10)) + .subscribe({ + error: () => { + expect(isLoading$.getValue()).toBe(false); + } + }); + }); +}); diff --git a/packages/rxjs/src/operators/flip-flag-on-finalize.operator.ts b/packages/rxjs/src/operators/flip-flag-on-finalize.operator.ts new file mode 100644 index 0000000..c19a2c2 --- /dev/null +++ b/packages/rxjs/src/operators/flip-flag-on-finalize.operator.ts @@ -0,0 +1,17 @@ +import { BehaviorSubject, defer, Observable, OperatorFunction, ReplaySubject } from 'rxjs'; +import { finalize, switchMap, take } from 'rxjs/operators'; + +export function flipFlagOnFinalize( + flagSubject$: BehaviorSubject | ReplaySubject +): OperatorFunction { + return (source: Observable): Observable => + defer(() => { + flagSubject$.pipe( + take(1), + switchMap((flagValue: boolean) => { + flagSubject$.next(!flagValue); + return source.pipe(finalize(() => flagSubject$.next(flagValue))); + }) + ); + }); +}