diff --git a/packages/store/src/internal/state-context-factory.ts b/packages/store/src/internal/state-context-factory.ts index 38ec2bac6..755722dc2 100644 --- a/packages/store/src/internal/state-context-factory.ts +++ b/packages/store/src/internal/state-context-factory.ts @@ -23,6 +23,7 @@ export class StateContextFactory { const root = this._internalStateOperations.getRootStateOperations(); return { + abortController: new AbortController(), getState(): T { const currentAppState = root.getState(); return getState(currentAppState, path); diff --git a/packages/store/src/internal/state-factory.ts b/packages/store/src/internal/state-factory.ts index 3d51e54bb..02a6c381c 100644 --- a/packages/store/src/internal/state-factory.ts +++ b/packages/store/src/internal/state-factory.ts @@ -25,7 +25,9 @@ import { mergeMap, takeUntil, finalize, - Observable + Observable, + fromEvent, + merge } from 'rxjs'; import { NgxsConfig } from '../symbols'; @@ -345,7 +347,7 @@ export class StateFactory implements OnDestroy { const { dispatched$ } = this._actions; for (const actionType of Object.keys(actions)) { const actionHandlers = actions[actionType].map(actionMeta => { - const cancelable = !!actionMeta.options.cancelUncompleted; + const cancellable = !!actionMeta.options.cancelUncompleted; return (action: any) => { const stateContext = this._stateContextFactory.createStateContext(path); @@ -384,9 +386,13 @@ export class StateFactory implements OnDestroy { defaultIfEmpty(undefined) ); - if (cancelable) { - const notifier$ = dispatched$.pipe(ofActionDispatched(action)); - result = result.pipe(takeUntil(notifier$)); + if (cancellable) { + const cancelled = merge( + dispatched$.pipe(ofActionDispatched(action)), + fromEvent(stateContext.abortController.signal, 'abort') + ); + + result = result.pipe(takeUntil(cancelled)); } result = result.pipe( diff --git a/packages/store/src/symbols.ts b/packages/store/src/symbols.ts index 58fbe1166..64f3fe2bc 100644 --- a/packages/store/src/symbols.ts +++ b/packages/store/src/symbols.ts @@ -99,6 +99,11 @@ export { StateOperator }; * State context provided to the actions in the state. */ export interface StateContext { + /** + * Abort controller provided for the individual action. + */ + abortController: AbortController; + /** * Get the current state. */