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))); + }) + ); + }); +}