angularngrx-signal-store

How to wait for a method set inside signalStore to finalize


I'm starting an angular application using ngrx signal, I've defined some methods, but I can't get my component code to wait for that method to finish

Store

export const OperationStore = signalStore(
  withState(operacaoStoreInitialState),
  withMethods((store, service = inject(OperationService)) => ({
    changeStatus: async (id: string, statusId: string) => {
      service.changeStatus(id, statusId)
        .subscribe({
          next: (data) => {
            console.log('2')
            ...some logic
            patchState(store, (state) => ({ data, loading: false }));
            console.log('3')
          },
          error: (e) => {
            ...some logic
          }
        })
    }
  })),

Service

changeStatus(id: string, statusId: string) {
  return this.http.patch<IResponse>(`${this.baseUrl}/${id}/status/${statusId}`, null)
}

Component

onFinalizar(id: string, statusId: string) {
  this.finalizandoOperacao = true
  this.habilitarBotoes = false
  console.log('1')
  this.operacaoStore.changeStatus(id, statusId)
  console.log('4')
  ...Here there would be a logic to be executed only when the above method was finished
}

I tried a few solutions but none of them worked. I tried async, await, promise.all

Always the order of the console output is 1, 4, 2 and 3 and I need the console output to be 1, 2, 3 e 4


Solution

  • To correctly achieve what you are aiming, you need to await for the promise in changeStatus() method. One way to approach this:

    import { firstValueFrom } from 'rxjs';
    
    export const OperationStore = signalStore(
      withState(operacaoStoreInitialState),
      withMethods((store, service = inject(OperationService)) => ({
        changeStatus: async (id: string, statusId: string) => {
          try {
            const data = await firstValueFrom(service.changeStatus(id, statusId));
            console.log('2');
            patchState(store, (state) => ({ data, loading: false }));
            console.log('3');
            return data;
          } catch (e) {
            console.error(e);
          }
        }
      }))
    );
    

    Make the component wait for the promise to be resolved:

    onFinalizar(id: string, statusId: string) {
      this.finalizandoOperacao = true;
      this.habilitarBotoes = false;
      console.log('1');
    
      this.operacaoStore.changeStatus(id, statusId).then(() => {
        console.log('4');
      }).catch(error => {
        console.error('Error in status change:', error);
      });
    }