rxjs / angular4 observable optimization

时间:2017-05-16 11:55:53

标签: angular rxjs observable

我对observables有一个优化问题:

我有两个接受用户名和密码的控件。当密码字段的值发生变化(带有去抖动)时,我想调用一个返回查询结果的可观察对象的服务方法,并用这些值填充模型。

返回的observable在服务错误的情况下抛出异常。但是我想在这种情况下用空数组填充模型。

我最初的实施:

  this.passwordControl.valueChanges
    .debounceTime(500)
    .filter(_ => this.usernameControl.valid && !this.usernameControl.pristine)
    .map((password) => new RequestAuthentication(this.usernameControl.value, password))
    .mergeMap(auth => this.orgService.getOrganizations(auth))
    .catch(_ => {
      return Observable.of([]);
    })
    .subscribe(orgs => {
      this.organizations = orgs;
    });

缺点是当执行catch函数时,我返回一个完成流的有限observable,我不能再听取这些更改了。

我的解决方案是嵌套observables:

this.passwordControl.valueChanges
  .debounceTime(500)
  .filter(_ => this.usernameControl.valid && !this.usernameControl.pristine)
  .map((password) => new RequestAuthentication(this.usernameControl.value, password))
  .subscribe(auth => {
    this.orgService.getOrganizations(auth)
      .catch(_ => Observable.of([]))
      .subscribe(orgs => {
        this.organizations = orgs;
      });
  });

但这似乎没有反应......我该如何避免这些嵌套的observable并保持代码干净?

1 个答案:

答案 0 :(得分:0)

一般不建议在另一个subscribe()内调用subscribe(),因为你只是用“subscribe hell”交换“callback hell”。此外,您正在丢失来自父Observable链的errorcomplete信号。尽管如此,你总是可以避免它。

因此,如果您不希望在发生错误时结束链,那么有一些运营商可以帮助您。具体来说:retry()retryWhen()(也是onErrorResumeNext()),可能还有更多。

如果您在发生错误信号时不想做任何事情,请使用retry()代替catch()

.mergeMap(...)
.retry()
.subscribe(orgs => {
  this.organizations = orgs;
});

如果您仍希望能够执行某些副作用(通知用户或其他),请在.do()之前使用retry()

.mergeMap(...)
.do(null, e => ...)
.retry()
.subscribe(orgs => {
  this.organizations = orgs;
});