简体   繁体   English

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

[英]How to handle errors in RxJS using Angular

I'm working on an Angular application which shows a list of items fetched from a RESTful API. 我正在使用一个Angular应用程序,该应用程序显示了从RESTful API获取的项目列表。 The content of the list depends on a query. 列表的内容取决于查询。 The query can be passed either by filling in an input field, using a submit button or by adding it to the URL as query parameter. 可以通过填写输入字段,使用提交按钮或将其添加为URL作为查询参数来传递查询。

To make sure everything runs in order and prevent asynchronous issues, I'm using RxJS . 为了确保一切正常运行并防止异步问题,我使用了RxJS

Now I'm wondering how I can handle errors, since they can occur in the middle of a stream, eg. 现在,我想知道如何处理错误,因为错误可能发生在流的中间,例如。 when the HTTP-request fails. 当HTTP请求失败时。

The query as input stream 查询作为输入流

These are two Observables , which both send a sequence of queries. 这是两个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;
  });

Fetching for the results 获取结果

The Observable below triggers when the query has been changed and fetches the results from the API. 下面的Observable会在查询已更改时触发,并从API获取结果。

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

Handling errors 处理错误

Now I don't know how to handle errors when eg. 现在我不知道如何处理错误,例如。 the getResultsForQuery throws an error. getResultsForQuery引发错误。 I would like to display the error instead of the results, but prevent the Observable from handling new events. 我想显示错误而不是结果,但是阻止Observable处理新事件。

Currently I've solved it by creating two new streams from the Observable, one to handle the result when successful and one when an error occurs. 目前,我已经通过在Observable中创建两个新的流来解决此问题,一个流在成功时处理结果,一个在发生错误时处理结果。 The response data for when the query was invalid contains an error property. 查询无效时的响应数据包含error属性。

Success stream 成功流

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

Error stream 错误流

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

Possible solutions 可能的解决方案

  1. I've read about throwing and catching errors , but the problem here is the stream seems to stop after the first error and doesn't trigger new events. 我已经读过有关引发和捕获错误的信息 ,但是这里的问题是流在第一个错误之后似乎停止了,并且不会触发新事件。

  2. Using onErrorResumeNext is described in the docs to ignore errors and make sure the stream continues after an error. 在文档中介绍了使用onErrorResumeNext来忽略错误,并确保流在出现错误后继续。 But I can't find a way to correctly 'handle' the error and show it to the end user. 但是我找不到正确地“处理”错误并将其显示给最终用户的方法。

Question

Is there a recommended approach on how to handle errors in a situation like this? 在这种情况下是否有建议的方法来处理错误? Is it necessary to create two streams for this, or is it recommended to throw an exception? 为此有必要创建两个流,还是建议抛出异常?

It's important that the user knows something went wrong, and the stream doesn't stop after the first error. 重要的是,用户必须知道出了点问题,并且在第一个错误发生后流不会停止。

The issue with catching logic is that it effectively terminates the sequence before it, which is why if you use it in your top level stream it will stop after a single exception. 捕获逻辑的问题在于,它有效地终止了它之前的序列,这就是为什么如果在顶级流中使用它,它将在单个异常后停止的原因。 I would recommend that you wrap your catch logic inside of a flatMapLatest . 我建议您将catch逻辑包装在flatMapLatest Then you can catch on the inner stream and transform the data to conform with what your downstream observers expect. 然后,您可以捕获内部流并转换数据以符合下游observers期望。

Something like this: 像这样:

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

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

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