简体   繁体   English

rxjs / angular4可观察的优化

[英]rxjs/angular4 observable optimization

I have an optimisation issue on observables: 我对observables有一个优化问题:

I have a two controls that accept an username and password. 我有两个接受用户名和密码的控件。 When the value of the password field changes (with a debounce), I want to call a service method that returns an observable of the query results and I fill a model with those values. 当密码字段的值发生变化(带有去抖动)时,我想调用一个返回查询结果的可观察对象的服务方法,并用这些值填充模型。

The returned observable throws an exception in case of service error. 返回的observable在服务错误的情况下抛出异常。 But I want to just fill the model with an empty array in such a case. 但是我想在这种情况下用空数组填充模型。

My original implementation: 我原来的实施:

  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;
    });

The drawback is that when the catch function is executed, I return a finite observable that completes the stream and I can't listen anymore to the changes. 缺点是当执行catch函数时,我返回一个完成流的有限observable,我不能再听取更改了。

My solution is to nest observables as such: 我的解决方案是嵌套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;
      });
  });

But this doesn't seem very reactive... How should I do to avoid these nested observables and keep the code clean ? 但这似乎没有反应......我该如何避免这些嵌套的observable并保持代码干净?

In general calling subscribe() inside another subscribe() isn't recommended because you're just exchanging "callback hell" with "subscribe hell". 在全体呼叫subscribe()内的另一个subscribe()不建议,因为你只是交换“回调地狱”与“地狱订阅”。 Also you're loosing error and complete signals from the parent Observable chain. 此外,您正在丢失errorcomplete来自父Observable链的信号。 Nonetheless, you can always avoid it. 尽管如此,你总是可以避免它。

So if you don't want to end the chain when an error occurs there're a few operators that can help you. 因此,如果您不想在发生错误时结束链,那么有一些运营商可以帮助您。 Specifically: retry() and retryWhen() (also onErrorResumeNext() ) and probably more. 具体来说: retry()retryWhen() (也是onErrorResumeNext() )可能更多。

If you don't want to do anything when an error signal occurs use retry() instead of catch() : 如果您在发生错误信号时不想执行任何操作,请使用retry()而不是catch()

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

If you still want to be able to perform some side-effect (notify user or whatever) use .do() before retry() : 如果您仍希望能够执行一些副作用(通知用户或其他.do()retry()之前使用.do() retry()

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM