#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 сгладит все выбросы в поток без отмены каких-либо текущих запущенных процессов.
Это объясняет, почему я всегда получал ПОСЛЕДНИЙ запрос, но не предыдущий.