Lazy Loading Action Handlers
import {
DestroyRef,
ɵisPromise,
runInInjectionContext,
type EnvironmentInjector
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { EMPTY, from, isObservable, Observable, of, switchMap } from 'rxjs';
export interface CallAsyncParams<T> {
injector: EnvironmentInjector;
actionLoader: () => Promise<T>;
asyncOperation: (impl: T) => Promise<void> | Observable<unknown> | void;
}
/**
* This function is intended for use within NGXS actions, which may load
* other action handlers asynchronously.
*
* The signature is the following:
*
* ```ts
* return callAsync({
* injector: this._environmentInjector,
* actionLoader: () => import('./action-handlers/validate-store-payment'),
* asyncOperation: (m) => m.validateStorePayment(ctx, this._store, action),
* });
* ```
*/
export function callAsync<T>(params: CallAsyncParams<T>) {
if (params.injector.destroyed) {
return EMPTY;
}
const destroyRef = params.injector.get(DestroyRef);
return from(params.actionLoader()).pipe(
switchMap(impl => {
const result = runInInjectionContext(params.injector, () => params.asyncOperation(impl));
// If the `asyncOperation` is asynchronous and requires the inner
// observable to be subscribed to, we then return it to `switchMap`.
if (isObservable(result) || ɵisPromise(result)) {
return result;
}
return of(undefined);
}),
takeUntilDestroyed(destroyRef)
);
}Usage
Directory Structure Suggestion
Last updated

