如何使用Angular处理RxJS中的错误

How to handle errors in RxJS using Angular

本文关键字:错误 RxJS 处理 何使用 Angular      更新时间:2023-09-26

我正在做一个Angular应用程序,它显示了一个从RESTful API获取的项目列表。列表的内容取决于查询。可以通过填写输入字段、使用提交按钮或将其作为查询参数添加到URL来传递查询。

为了确保一切正常运行并防止异步问题,我使用RxJS。

现在我想知道如何处理错误,因为它们可能发生在流的中间,例如。当http请求失败时。

查询作为输入流

这是两个Observables,它们都发送一个查询序列。

// first observable for the submit button
submitFormObservable = $scope.$createObservableFunction('search');
// second observable for when the input value changes
inputObservable = $scope.$toObservable('query')
  .map(function (change) {
    return change.newValue;
  });

获取结果

下面的Observable在查询被更改时触发,并从API获取结果。

var mainStream = Rx.Observable.merge([submitFormObservable, inputObservable])
  .where(function (query) {
    return query && query.length > 0;
  })
  .debounce(400)
  .distinctUntilChanged()
  .select(getResultsForQuery)
  .switchLatest();

处理错误

现在我不知道如何处理错误,当eg。getResultsForQuery抛出错误。我想显示错误而不是结果,但要阻止Observable处理新事件。

目前我已经通过从Observable中创建两个新的流来解决这个问题,一个处理成功时的结果,一个处理发生错误时的结果。查询无效时的响应数据包含error属性。

<<p> 成功流/strong>
// stream containing the album information from LastFm
mainStream
  .filter(function (response) {
    return !response.data.error;
  })
  .map(function (response) {
    return response.data.result;
  })
  .subscribe(function (result) {
    $scope.error = undefined;
    $scope.result = result;
  });

错误流

mainStream
  .filter(function (response) {
      return response.data.error;
    })
   .map(function (response) {
      return response.data;
  });
  .subscribe(function (error) {
    $scope.result = [];
    $scope.error = error;
  });

可能的解决方案
  1. 我读过关于抛出和捕获错误,但这里的问题是流似乎在第一个错误后停止,并且不触发新的事件。

  2. 使用onErrorResumeNext在文档中描述了忽略错误并确保流在错误发生后继续。但是我找不到正确"处理"错误并显示给最终用户的方法。

在这种情况下如何处理错误有什么推荐的方法吗?是否有必要为此创建两个流,还是建议抛出异常?

重要的是用户知道哪里出错了,并且流不会在第一个错误之后停止。

捕获逻辑的问题是它有效地终止了它之前的序列,这就是为什么如果您在顶级流中使用它,它将在单个异常后停止。我建议将catch逻辑包装在flatMapLatest中。然后你可以抓住内部流并转换数据以符合下游observers的期望。

像这样:

var mainStream = Rx.Observable.merge([submitFormObservable, inputObservable])
  .where(function (query) {
    return query && query.length > 0;
  })
  .debounce(400)
  .distinctUntilChanged()
  .selectSwitch(function(input) {
    return getResultsForQuery(input)
            .map(function(response) {
              return {result : response.data.result};
            })
            .catch(function(e) {
              return Rx.Observable.just({error : error});
            });
  });
mainStream.subscribe(function(r) {
  $scope.result = r.result || [];
  $scope.error = r.error;
});