【问题标题】:RxJS Update State and PassthroughRxJS 更新状态和传递
【发布时间】:2018-12-03 14:51:12
【问题描述】:

我有一个用户库,用于我组织中的多个 Angular 应用程序。作为重构/新版本,我们希望转向基于状态的服务,其接口类似于:

export interface UserService {
    user: Observable<User>
    getProfile(url: string): Observable<User>
    updateProfile(url: string): Observable<User>
}

这样,消费者可以将组件绑定到UserService.user,知道数据将始终是最新的,并在按钮或后台活动等中调用get/update函数。

澄清:用户库旨在用于使用 ngRx 的应用程序,以及那些不想要如此繁重但仍需要基于 observable 的用户绑定的应用程序。

所以我将这样的函数连接起来(略有不同):

public getProfile(url: string): Observable<User> {
    const obs = this._http.get<User>(url);
    obs.subscribe(profile => this.setProfile(profile));
    return obs;
}

其中setProfile 更新UserService.user 以只读方式返回的内部订阅。

有一次我的消费者应用程序使用ngRx 进行其余的状态管理。在使用我的图书馆时,我们发现了一些奇怪的现象:

  1. 当包裹在 ngRx 效果中时,有时任何使用 Angular 的 HttpClient 的函数都会被多次调用。为了解决这个问题,我使用HttpClient 的任何函数都以.publishLast().refCount() 结尾,以确保只进行一次HTTP 调用。

  2. 如果调用失败,消费者无法捕获异常。例如,this.authService.getProfile().catch(error =&gt; alert(error)) 永远不会被调用。为了解决这个问题,我现在正在修改他们订阅的函数:obs.subscribe(profile =&gt; this.setProfile(profile), error =&gt; Observable.throw(error));

在 Angular 中实现“状态存储”服务时这是正常行为吗?

编辑:示例 ngRx 效果(请注意,这是真正的实现,我上面发布的内容是从我们的实际实现中简化的):

public BiographyUpdate: Observable<any> = this._actions.pipe(
    ofType(AuthActionTypes.BIOGRAPHY_UPDATE),
    map((action: BiographyUpdate) => action.payload),
    switchMap(bio => this._auth.update(`${Environment.Endpoints.Users}/users/sync/biography`, action)
      .map(profile => new BiographyUpdateSuccess(profile.biography))
      .catch(error => {
        console.log("AM I BEING HIT?");
        return Observable.of(new BiographyUpdateFailure(error.toString()))
      })
    )
  );

【问题讨论】:

  • 可以分享ngrx效果代码吗?

标签: angular rxjs ngrx angular-httpclient


【解决方案1】:

一旦你调用了subscribe 事件,它就会被触发并在 subscribe 方法中解析结果(正确的结果或错误)。所以当时,你调用this.authService.getProfile().catch 方法,异步事件已经被触发并完成。这就是它不调用的原因。

您可以在getProfile 中移动catch 运算符,也可以从getProfile 返回可观察对象而不订阅它。

public getProfile(url: string): Observable<User> {
    return this._http.get<User>(url)
            .pipe( tap( profile => this.setProfile(profile))); 
}

现在通过authService 服务订阅它

this.authService.getProfile()
  .subscribe(profile =>  // do the work)
  .catch(error => alert(error))

【讨论】:

  • 谢谢!让我试试看。
  • 工作得很好!非常感谢!
猜你喜欢
  • 2020-03-09
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-30
  • 2021-04-07
  • 2021-04-24
  • 2020-04-29
相关资源
最近更新 更多