ngxs dispatch completes before async action completes

Viewed 438

"@ngxs/store": "^3.7.2"

We are using ngxs with async actions. According to the documentation, both snippets (with await/without await) should be equivalent.

However, when dispatched like this, the first action call waits until the action is completed, the second action implementation does not wait (see outputs below):

this.store.dispatch(new CreatePackageAction(pkg))
  .subscribe(
    () => console.log('Dispatch next'),
    () => console.log('Dispatch error'),
    () => console.log('Dispatch completed')
  );

Without async/await (as expected)

 @Action(CreatePackageAction)
 createPackageVersion(ctx: StateContext<IPackageStateModel>, payload: CreatePackageAction) {
    console.log('createPackage coming up');

    return this.packageService.createPackage(payload.packageCreate)
      .then(() => console.log('createPackage done'));
  }

17:49:54.360 createPackage coming up
17:49:54.418 createPackage done
17:49:54.431 Dispatch next
17:49:54.432 Dispatch completed

With async/await (not as expected)

  @Action(CreatePackageAction)
  async createPackageVersion(ctx: StateContext<IPackageStateModel>, payload: CreatePackageAction) {
    console.log('createPackage coming up');  

    await this.packageService.createPackage(payload.packageCreate);
    console.log('createPackage done');
  }

17:47:39.482 createPackage coming up
17:47:39.484 Dispatch next
17:47:39.484 Dispatch completed // does not wait, **WHY?**
17:47:39.535 createPackage done
1 Answers

The async/await action function does not return any value so this causes NGXS to operate in "fire and forget" mode and your dispatch next code fires before action completion.

If you execute several async/await calls within your action, and then return the last promise call or an observable, it should execute as you'd expect. To test this, you can finish your action by returning an empty observable (like return of({}) with rxjs of operator).

Related