Может ли эффект ngrx отправлять одно и то же действие дважды

#angular #rxjs #ngrx

#angular #rxjs #ngrx

Вопрос:

У меня есть эффект ngrx. Из этого эффекта я хотел бы вызвать несколько вызовов одного и того же действия ngrx, но с разными параметрами. Вот что я сейчас делаю:

 @Effect({dispatch: true}) 
    public handleNodeWillReceiveFocus$ = this.actions$
    .pipe(
      ofType(nodeWillReceiveFocus),
      concatMap( payload => [
      
        lookuplistShouldRefresh({listname:"billboards"}),
        lookuplistShouldRefresh({listname:"microforms"}),
        
        nodeDidReceiveFocus(payload),
        
      ]),
      
      ); 
  

Действие выглядит следующим образом:

 import { createAction, props } from '@ngrx/store';
export const lookuplistShouldRefresh = createAction(
  '[lookuplists] lookuplistShouldRefresh',
  props<{ listname:string }>()
);
  

Поведение, которое я наблюдаю, заключается в том, что, похоже, отправляется только одно из действий lookuplistShouldRefresh (последнее). Если я поменяю местами два вызова, я получу вызов «рекламные щиты».

Оба действия приводят к мутациям хранилища.

Возможно ли отправлять одно и то же действие несколько раз из эффекта с разными параметрами? Я думал, что concatMap запускал все последовательно …?

Обновление: я добавил некоторое ведение журнала, и два действия отправляются правильно, но что-то не так в другом месте.

Вот второй обработчик эффекта:

 export class handleLookuplistShouldRefreshEffect {

    constructor(
        private actions$: Actions,
        private lookuplistAPI: LookuplistAPIService,
      ) {}

      
    @Effect({dispatch: true}) 
    public handleLookupListShouldRefresh$ = this.actions$
    .pipe(
      ofType(lookuplistShouldRefresh),
      tap((payload) => {
        console.log(`EFFECT handleLookupListShouldRefresh has FIRST ${JSON.stringify(payload)}`);
      }),
      switchMap((payload) => this.lookuplistAPI.getLookupList(payload)),
      tap((payload) => {
        console.log(`EFFECT handleLookuplistShouldRefreshEffect has SECOND ${JSON.stringify(payload)}`);
      }),
      concatMap( payload => [
        lookuplistDidRefresh({listname:payload["listname"],items:payload["items"]}),
        
      ]),
      
      );

}
  

API выглядит следующим образом:

 export class LookuplistAPIService {

  constructor(private store: Store, private zhttpSvc: ZhttpService) { }

  getLookupList(payload){
    try{
      
      console.log(`getLookupList has payload: ${JSON.stringify(payload)}`);
      const path = this.getPathFromListname(payload.listname);
      
      return this.zhttpSvc.httpGet(path);
       
    }catch(exc){
      console.log(`BANG in getLookupList`);
      return of({});
    }
  }

  getPathFromListname(listname){
    switch(listname){
      case "microforms":
        return "/microform/lookuplist";
        break;
      case "billboards":
        return "/billboard/lookuplist";
        break;
    }
    
  }
}
  

HttpGet выглядит так:

 public httpGet(path){
    
    
    const options = {
      withCredentials: true // Allows cookies to be read/set
    };

    
    return this.http.get(`${environment.apiUrl}${path}`,options);
    
  }
  

Дважды регистрируется сообщение «ЭФФЕКТ handleLookupListShouldRefresh имеет ПЕРВЫЙ …».
«getLookupList имеет полезную нагрузку …» регистрируется дважды.
«ЭФФЕКТ handleLookuplistShouldRefreshEffect имеет ВТОРОЙ …» регистрируется ОДИН РАЗ.

Очевидно, я делаю что-то не так в том, как организован этот код. Кто-нибудь может увидеть, что я делаю неправильно?

Ответ №1:

Хорошо, итак, я понял это. Проблема заключается в том, что я использую switchMap в handleLookuplistShouldRefreshEffect

switchMap начнет обработку первого запроса, но отменит первый запрос, как только поступит второй запрос. Он «переключается» на второе излучение.

Я изменил switchMap на flatMap — flatMap сгладит все выбросы в поток без отмены каких-либо текущих запущенных процессов.

Это объясняет, почему я всегда получал ПОСЛЕДНИЙ запрос, но не предыдущий.