Cancellation

If you have an async action, you may want to cancel a previous Observable if the action has been dispatched again. This is useful for canceling previous requests like in a typeahead.

Basic

For basic scenarios, we can use the cancelUncompleted action decorator option.

import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService, private actions$: Actions) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res))
    ));
  }
}

Using AbortSignal

Starting from NGXS v21, the StateContext includes an abortSignal property that provides a standardized way to handle cancellation of asynchronous operations. This is particularly useful when working with cancelUncompleted actions.

Why AbortSignal?

The AbortSignal provides a standard browser API to detect and respond to cancellations. When an action marked with cancelUncompleted: true is canceled (because a new instance was dispatched), the abortSignal will be aborted, allowing you to:

  • Check cancellation status in async/await code

  • Pass the signal to fetch requests for automatic cancellation

  • Clean up resources gracefully

  • Avoid unnecessary state updates

With Async/Await

When using async/await, check ctx.abortSignal.aborted after await points to handle cancellation:

With Fetch API

The AbortSignal works seamlessly with the Fetch API:

With Observables

When you return an Observable from an action handler, NGXS automatically unsubscribes when the abortSignal is aborted. You don't need to manually check the signal:

Advanced

For more advanced cases, we can use normal Rx operators.

Last updated