【问题标题】:Ngrx Effects: Conditionally return action inside switchMap instead of http responseNgrx 效果:有条件地在 switchMap 中返回操作而不是 http 响应
【发布时间】:2018-10-01 14:37:19
【问题描述】:

我目前正在开发一个 Angular 5 应用程序,该应用程序将在 ngrx-store 中使用一些缓存策略,以允许用户查看项目并返回主列表而无需再次发出请求。

我正在使用 Effect 来请求数据并使用 reducer 根据我的 htp 响应更新我的全局状态。如您所见,成功时触发 RequestPartnersSuccess 操作,错误时触发 RequestPartnersFail。

我的全局状态中的属性“internalAppDynamic.searchPartners.recoverLatest”指示我是否应该从缓存中恢复我的列表,在这种情况下,效果应该在这个“if”语句中返回一个方法并完成我的流。

@Effect()
  loadPartners$ = this.actions$
    .ofType(SearchPartnersActions.REQUEST_PARTNERS)
    .withLatestFrom(this.store$, (action, state) => {
      action = Object.assign(action, {recoverLatest: state.internalAppDynamic.searchPartners.recoverLatest})
      return action
    })
    .pipe(switchMap((action: any) => {
      if (action.recoverLatest) {
        return new SearchPartnersActions.RequestPartnersRecoverCache()
      }
      return this.internalPartnersService.getPartners(action.payload).pipe(
        map(partners => new SearchPartnersActions.RequestPartnersSuccess(partners)),
        catchError(error => of(new SearchPartnersActions.RequestPartnersFail(error)))
      )
    }))

这是我的服务中的 getPartners() 函数:

getPartners (body): Observable<any> {
    return this.http
    .post(this._baseUrl + 'internal-app/get-partners', body, this.httpOptions)
    .pipe(catchError((error: any) => this.errorHandler(error)))
  }

问题是我找不到实现这个结果的方法。我是 rxjs 和 Observables 的新手,我认为 switchMap 运算符期望另一种返回,而不是我的 SearchPartnersActions.RequestPartnersRecoverCache() 类的新实例。

我可以做些什么来达到预期的效果?有人可以更好地向我解释一下这个 Observable 流的期望是什么吗?

谢谢!

【问题讨论】:

    标签: angular rxjs angular5 ngrx ngrx-effects


    【解决方案1】:

    我能够通过创建一个辅助 observable 来实现所需的行为,以便能够在流中传递我的操作,如下所示:

      auxObservable () {
        return Observable.create((observer) => {
          observer.next()
        })
      }
    
      @Effect()
      loadPartners$ = this.actions$
        .ofType(SearchPartnersActions.REQUEST_PARTNERS)
        .withLatestFrom(this.store$, (action, state) => {
          action = Object.assign(action, {recoverLatest: state.internalAppDynamic.searchPartners.recoverLatest})
          return action
        })
        .pipe(switchMap((action: any) => {
          if (action.recoverLatest) {
            return this.auxObservable().pipe(
              map(res => new SearchPartnersActions.RequestPartnersRecoverCache())
            )
          }
          return this.internalPartnersService.getPartners(action.payload).pipe(
            map(partners => new SearchPartnersActions.RequestPartnersSuccess(partners)),
            catchError(error => of(new SearchPartnersActions.RequestPartnersFail(error)))
          )
        }))
    

    如果您需要在流中传递您的操作对象以将其类型或负载用于其他用途,您应该将其作为 auxObservable 参数传递,如下所示:

      auxObservable (action) {
        return Observable.create((observer) => {
          observer.next(action)
        })
      }
    
      @Effect()
      loadPartners$ = this.actions$
        .ofType(SearchPartnersActions.REQUEST_PARTNERS)
        .withLatestFrom(this.store$, (action, state) => {
          action = Object.assign(action, {recoverLatest: state.internalAppDynamic.searchPartners.recoverLatest})
          return action
        })
        .pipe(switchMap((action: any) => {
          if (action.recoverLatest) {
            return this.auxObservable(action).pipe(
              map(res => new SearchPartnersActions.RequestPartnersRecoverCache())
            )
          }
          return this.internalPartnersService.getPartners(action.payload).pipe(
            map(partners => new SearchPartnersActions.RequestPartnersSuccess(partners)),
            catchError(error => of(new SearchPartnersActions.RequestPartnersFail(error)))
          )
        }))
    

    我认为将来有人可能需要这种技术,所以我分享我的解决方案 =)

    如果有人能想出更好的方法来拦截满足条件时的默认流行为并触发不同的reducer案例,请与我们分享!

    更新:

    正如 Alexander 指出的那样,auxObservable 不是必需的,可以只返回 of(new SearchPartnersActions.RequestPartnersRecoverCache()),确保从 rxjs 导入了“of”运算符。

    谢谢!

    【讨论】:

    • 你不需要 auxObservable 和管道。只需return Observable.of(new WhateverObject())
    • 感谢您的回答!这对我有帮助。但是这个“of”运算符是如何在流中工作的呢?在我的解决方案中,通过使用函数创建观察者,我可以触发多个 next() 函数,甚至可以使用observer.complete 控制我的流。在“of”运算符中,它只是将“newwhateverObject”传递到流中,就像 Observer.create 中的 observer.next() 一样?
    • 我刚刚查看了 rxjs api,'of' 方法与 'create' 完全相同,在 next() 中按顺序传递所有参数,它们发出一个 .complete。因此,除非您在 next() 函数之间需要额外的逻辑,否则最好使用 Observable.of(val1, val2, val3,...) 而不是从函数创建 Observable。再次感谢亚历山大!
    • 你没问题。做得好!请更新您的答案以反映这一点,因为可能会教其他不太熟悉 rx 的人使用不必要的构造。
    • 找到了。您需要做的就是像管道中的任何其他操作一样使用of 运算符:something.pipe(switchMap(s =&gt; of(new SomeObject()))),当然还有导入of 运算符:import { of } from 'rxjs/observable/of';
    猜你喜欢
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 2019-03-30
    • 2023-03-17
    • 2021-12-08
    相关资源
    最近更新 更多