Skip to content

Instantly share code, notes, and snippets.

@arnotes
Last active February 16, 2021 12:36
Show Gist options
  • Save arnotes/cb99af39bbad93a792814219116309ae to your computer and use it in GitHub Desktop.
Save arnotes/cb99af39bbad93a792814219116309ae to your computer and use it in GitHub Desktop.
const tapWhenUnsubscribed = <T>(source$: Observable<T>) => (
fn: (x: T) => void
) =>
new Observable<T>(observer => {
let closedFromSource = false;
const subscription = source$.subscribe(
x => {
observer.next(x);
},
e => {
closedFromSource = true;
observer.error(e);
},
() => {
closedFromSource = true;
observer.complete();
}
);
return () => {
if (!closedFromSource) fn();
subscription.unsubscribe();
};
});
import { defer, Observable, MonoTypeOperatorFunction } from 'rxjs';
import { tap, finalize } from 'rxjs/operators';
export enum FinalizeReason {
Unsubscribe = 'unsubscribe',
Complete = 'complete',
Error = 'error',
}
/**
* @todo(): Review when https://github.com/ReactiveX/rxjs/issues/2823 is resolved.
* Just like `finalize()` but passes to its callback also `reason` why the chain is being
* disposed (chain completed, errored or on unsubscription).
*
* @param callback (reason: FinalizeReason) => void
*/
export const finalizeWithReason = <T>(callback: (reason: FinalizeReason) => void): MonoTypeOperatorFunction<T> =>
(source: Observable<T>) =>
defer(() => {
let completed = false;
let errored = false;
return source.pipe(
tap({
error: () => errored = true,
complete: () => completed = true,
}),
finalize(() => {
if (errored) {
callback(FinalizeReason.Error);
} else if (completed) {
callback(FinalizeReason.Complete);
} else {
callback(FinalizeReason.Unsubscribe);
}
}),
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment