UNPKG

@ngneat/loadoff

Version:

<p align="center"> <img width="20%" height="20%" src="./logo.svg"> </p>

129 lines (121 loc) 3.52 kB
import { defer, BehaviorSubject, pipe, of } from 'rxjs'; import { finalize, map, startWith, catchError, tap, scan } from 'rxjs/operators'; function loadingTracker(tracker) { return function (source) { return defer(() => { tracker.next(true); return source; }).pipe(finalize(() => tracker.next(false))); }; } function loadingFor(...keys) { const result = {}; for (const key of keys) { const subject = new BehaviorSubject(false); result[key] = { inProgress$: subject.asObservable(), track() { return loadingTracker(subject); }, }; } return result; } class AsyncState { constructor(state = {}) { this.res = undefined; this.error = undefined; this.loading = true; this.success = false; this.complete = false; Object.assign(this, state); } } function createAsyncState(state = {}) { return new AsyncState(state); } function createSyncState(res) { return new AsyncState({ loading: false, complete: true, res, }); } function isSuccess(state) { return state.success; } function hasError(state) { return !!state.error; } function isComplete(state) { return state.complete; } function isLoading(state) { return state.loading; } function toAsyncState() { return pipe(map((res) => { return new AsyncState({ res, loading: false, complete: true, success: true, }); }), startWith(new AsyncState()), catchError((error) => { console.error(error); return of(new AsyncState({ error, loading: false, complete: true, })); })); } function createAsyncStore() { const store = new BehaviorSubject(new AsyncState()); function update(data) { let resolved = data; if (typeof data === 'function') { resolved = data(store.getValue().res); } store.next(new AsyncState({ res: resolved, loading: false, complete: true, success: true, })); } return { value$: store.asObservable(), getValue: store.getValue(), update, track() { return pipe(tap({ next(data) { update(data); }, error(err) { store.next(new AsyncState({ error: err, loading: false, complete: true, })); }, })); }, }; } /** * Operator that retains the previous response on a new emission of an AsyncState item. * This can be useful for implementing a refresh mechanism, where you want to keep displaying the old value while fetching a new value */ function retainResponse(startWithValue = createAsyncState()) { return pipe(startWith(startWithValue), scan((acc, val) => new AsyncState(Object.assign(Object.assign({}, val), { res: val.success ? val.res : acc.res })))); } function someLoading() { return map(states => states.some(s => s.loading)); } /** * Generated bundle index. Do not edit. */ export { AsyncState, createAsyncState, createAsyncStore, createSyncState, hasError, isComplete, isLoading, isSuccess, loadingFor, retainResponse, someLoading, toAsyncState }; //# sourceMappingURL=ngneat-loadoff.mjs.map