Skip to content

Instantly share code, notes, and snippets.

@ezzabuzaid
Last active February 23, 2024 11:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ezzabuzaid/e89967ad103e699266c4bc9c23c46e6b to your computer and use it in GitHub Desktop.
Save ezzabuzaid/e89967ad103e699266c4bc9c23c46e6b to your computer and use it in GitHub Desktop.
Extract loading state from observable
import {
Observable,
ObservableInput,
ReplaySubject,
delay,
distinctUntilChanged,
finalize,
from,
of,
tap,
} from 'rxjs';
export function extractLoading<T>(
source: ObservableInput<T>,
): [Observable<boolean>, Observable<T>] {
const loading$ = new ReplaySubject<boolean>();
const tracked$ = new Observable<T>((subscriber) => {
loading$.next(true);
const subscription = from(source)
.pipe(
tap(() => loading$.next(false)),
finalize(() => loading$.next(false)),
)
.subscribe(subscriber);
return () => {
loading$.next(false);
loading$.complete();
subscription.unsubscribe();
};
});
return [loading$.pipe(distinctUntilChanged()), tracked$];
}
const [loading, source] = extractLoading(fetch('https://jsonplaceholder.typicode.com/posts/1').then(
(response) => response.json(),
));
// OR with lazy calling
const [loading, source] = extractLoading(defer(() => fetch('https://jsonplaceholder.typicode.com/posts/1').then(
(response) => response.json(),
)));
source.subscribe({
next: (value) => {
console.log({ source: value });
},
});
loading.subscribe({
next: (value) => {
console.log({ loading: value });
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment