首页 > 解决方案 > 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);
    
  }

“EFFECT handleLookupListShouldRefresh has FIRST ...”被记录两次。“getLookupList has payload...”被记录了两次。“EFFECT handleLookuplistShouldRefreshEffect has SECOND ...”记录一次。

显然,我在组织这段代码的方式上做错了。谁能看到我做错了什么?

标签: angularrxjsngrx

解决方案


好的,所以我想通了。问题在于我在 handleLookuplistShouldRefreshEffect 中使用 switchMap

switchMap 将开始处理第一个请求,但会在第二个请求到达后立即取消第一个请求。它“切换”到第二次发射。

我将 switchMap 更改为 flatMap - flatMap 会将所有排放压平到流中,而不会取消任何当前正在运行的进程。

这解释了为什么我总是收到最后一个请求,而不是之前的请求。


推荐阅读