Rxjs 在NgRx中远程操作前完成功能

Rxjs 在NgRx中远程操作前完成功能,rxjs,ngrx,ionic5,Rxjs,Ngrx,Ionic5,我对NgRx的比赛条件有问题。在下面的示例中,我将在启动异步远程操作的同时异步显示一个加载对话框。但远程操作可能会在完全构建加载对话框之前完成并触发dismissLoadingDialog(),这会导致控制台错误 在远程操作开始之前,NgRx中完成presentLoadingDialog()的好策略是什么 @Effect() fetchServerData$ = this.actions$.pipe( ofType<FetchServerData>(ActionTypes.F

我对NgRx的比赛条件有问题。在下面的示例中,我将在启动异步远程操作的同时异步显示一个加载对话框。但远程操作可能会在完全构建加载对话框之前完成并触发dismissLoadingDialog(),这会导致控制台错误

在远程操作开始之前,NgRx中完成presentLoadingDialog()的好策略是什么

@Effect() fetchServerData$ = this.actions$.pipe(
    ofType<FetchServerData>(ActionTypes.FetchServerData),
    switchMap(action => {
      this.presentLoadingDialog('...loading');
      return this.dataService.fetchData(action.payload).pipe(
        map(result => {
          this.dismissLoadingDialog();            
          return new FetchServerDataSuccess(result);
        }),
        catchError(err => of(new FetchServerDataFail(err)))
      );
    })
  );


async presentLoadingDialog(message: string): Promise<void> {
    this.isLoading = true;
    return this.loadingCtrl
      .create({
        duration: 5000,
        message: message
      })
      .then(loadingDialog => {
        loadingDialog.present().then(() => {
          if (!this.isLoading) {
            loadingDialog.dismiss();
          }
        });
      });
  }

  async dismissLoadingDialog() {
    this.isLoading = false;
    if (!isNullOrUndefined(this.loadingCtrl)): Promise<boolean> {
      return this.loadingCtrl.dismiss();
    }
  }
@Effect()fetchServerData$=此.actions$.pipe(
ofType(ActionTypes.FetchServerData),
开关映射(操作=>{
这个.presentLoadingDialog(“…加载”);
返回这个.dataService.fetchData(action.payload.pipe)(
映射(结果=>{
这是.dismissLoadingDialog();
返回新的FetchServerDataSucces(结果);
}),
catchError(err=>of(新的FetchServerDataFail(err)))
);
})
);
async presentLoadingDialog(消息:string):承诺{
this.isLoading=true;
返回此参数。loadingCtrl
.创造({
持续时间:5000,
信息:信息
})
。然后(加载对话框=>{
加载dialog.present()。然后(()=>{
如果(!this.isLoading){
loadingDialog.disclose();
}
});
});
}
异步dismissLoadingDialog(){
this.isLoading=false;
如果(!isNullOrUndefined(this.loadingCtrl)):承诺{
返回此参数。loadingCtrl.Disclose();
}
}

我看到的标准是,在您所在的州有加载和加载标志。当您分派一个加载操作时,在该操作触发http请求之前,reducer会用loading:true和loaded:false更新状态。然后,操作开关映射到一个操作,该操作使用响应和loading:false和loaded:true更新状态

然后,在组件中有一个用于加载标志的选择器,并订阅该选择器以打开和关闭对话框

this.loadingSub = loadings$.subscribe(loading => {
  if (loading) {
    this.presentLoadingDialog('...loading');
  } else {
    this.loadingDialog.dismiss();
  }
});
取消onDestroy中的订阅


应该由您的组件来显示UI组件,我认为调用加载对话框的操作并不是一个操作问题。我不推荐使用状态管理的核心来调用UI组件。

Ionic的LoadingController
create
方法返回一个承诺,该承诺在加载程序创建完成时解决。因此,您可以在效果的可观察链中使用它:

presentLoadingDialog(消息:字符串){
const loader=this.loadingCtrl
.创造({
持续时间:5000,
信息:信息
});
返回加载器.present();
}
dismissLoadingDialog(){
this.loadingCtrl.Disclose();
}
@Effect()fetchServerData$=this.actions$.pipe(
ofType(ActionTypes.FetchServerData),
switchMap(action=>forkJoin(来自(action)的(this.presentLoadingDialog(“…loading”)),
switchMap(([\ux,action])=>this.dataService.fetchData(action.payload).pipe(
点击(()=>this.dismissLoadingDialog()),
映射(结果=>new FetchServerDataSuccess(结果)),
catchError(err=>{
这是.dismissLoadingDialog();
返回(新的FetchServerDataFail(err))
})
))
);

我创建了一个名为ez state的简单状态库,如果您感兴趣,可以看看它在加载微调器时的用法。比ngrx简单得多。在传统的angular应用程序中,我同意这一点,但我们使用的是Ionic 5,它使用本机加载对话框,必须从.ts文件启动。我可以编写一个自定义组件来显示/改为隐藏,但似乎我应该能够将加载对话框observable插入流中。但是商店不应该知道UI问题,您可以侦听加载$observable并在组件中启动对话框。我肯定会拒绝在商店中使用UI组件的拉取请求。商店生成observable发射,故事结束在我的选项中,它不应该有任何UI知识。我编辑了这个问题以调用组件中的对话函数,而不是存储。这是一个旧模式,不推荐使用。嘿,威尔,谢谢你的提示,我想这就是我要找的。有机会的话,你能完成这个链吗?我“我仍在尝试处理Rxjs运算符,但无法完全弄清楚我的fetchData()observable在其中的适用性。之后我将奖励您。看起来它起作用了!我只是做了一些修改:我更改了presentLoadingDialog方法以返回一个主题,因此我删除了from()运算符,然后我相信forkJoin中缺少了一个括号,因此forkJoin行最终看起来像下面的注释:switchMap(action=>forkJoin(this.presentLoadingDialog(“…load”),of(action)),很高兴我能帮上忙!