Matt
Matt

Reputation: 2213

How to make an ngrx effect wait for an async function

I am using node-keytar to store tokens in an Electron app. It uses promises and as such I need to wait for the Promise to resolve to get the token.

The effect I'm trying to create will call the auth service to get the token and then send that token to the backend API using an Angular http call. The issue here is calling the service function in the Effect. As the service function needs to await the response keytar the whole function has to be async, but as far as I can see there is no way to make the Effect itself async with the async keyword.

Is there a different architecture I should be using here? I've tried using .then() and returning the success action from within, but this throws type errors.

The effect (which currently has the error Type Observable<{}> is not assignable to type Observable<Action>):

  setAccount$: Observable<Action> = this.actions$.pipe(
    ofType<SetCurrentAccountPending>(AccountActions.ActionTypes.SetCurrentAccountPending),
    switchMap(action => {
      return this.accountService.setCurrentAccount(action.payload).pipe(
        map(
            () => new AccountActions.SetCurrentAccountSuccess(action.payload)
          ),
          catchError(() => {
            return of(new AccountActions.SetCurrentAccountFailure());
          })
        );
    })
  );

The service function:

async setCurrentAccount(id: string) {
    const password = await AccountHandler.getPasswordFromManager(id);
    const body = {password: password};
    return this.httpClient.post(environment.localApi + '/accounts/' + id, body);
}

Upvotes: 6

Views: 7609

Answers (1)

Flignats
Flignats

Reputation: 1274

Does something like this help?

  setAccount$: Observable<Action> = this.actions$.pipe(
    ofType<SetCurrentAccountPending>(AccountActions.ActionTypes.SetCurrentAccountPending),
    switchMap(action => this.accountService.setCurrentAccount(action.payload)),
    map(data => new AccountActions.SetCurrentAccountSuccess(data)),
    catchError(error => of(new AccountActions.SetCurrentAccountFailure()))
  );

Upvotes: 8

Related Questions