如何使用 Angular 处理 RxJS 中的错误
How to handle errors in RxJS using Angular
我正在开发一个 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();
处理错误
现在我不知道如何处理错误,例如。 getResultsForQuery
抛出错误。
我想显示错误而不是结果,但阻止 Observable
处理新事件。
目前我已经通过从 Observable 创建两个新流解决了这个问题,一个在成功时处理结果,一个在发生错误时处理结果。查询无效时的响应数据包含 error
属性.
成功流
// 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;
});
可能的解决方案
我读过 throwing and catching errors,但这里的问题是流似乎在第一个错误后停止并且不会触发新事件。
使用onErrorResumeNext
是described in the docs忽略错误并确保流在错误后继续。但是我找不到正确 'handle' 错误并将其显示给最终用户的方法。
问题
在这种情况下,是否有推荐的处理错误的方法?是否需要为此创建两个流,还是建议抛出异常?
让用户知道出了什么问题很重要,并且流不会在第一个错误后停止。
捕获逻辑的问题是它有效地终止了它之前的序列,这就是为什么如果你在你的顶级流中使用它它会在一个异常后停止。我建议您将捕获逻辑包装在 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;
});
我正在开发一个 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();
处理错误
现在我不知道如何处理错误,例如。 getResultsForQuery
抛出错误。
我想显示错误而不是结果,但阻止 Observable
处理新事件。
目前我已经通过从 Observable 创建两个新流解决了这个问题,一个在成功时处理结果,一个在发生错误时处理结果。查询无效时的响应数据包含 error
属性.
成功流
// 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;
});
可能的解决方案
我读过 throwing and catching errors,但这里的问题是流似乎在第一个错误后停止并且不会触发新事件。
使用
onErrorResumeNext
是described in the docs忽略错误并确保流在错误后继续。但是我找不到正确 'handle' 错误并将其显示给最终用户的方法。
问题
在这种情况下,是否有推荐的处理错误的方法?是否需要为此创建两个流,还是建议抛出异常?
让用户知道出了什么问题很重要,并且流不会在第一个错误后停止。
捕获逻辑的问题是它有效地终止了它之前的序列,这就是为什么如果你在你的顶级流中使用它它会在一个异常后停止。我建议您将捕获逻辑包装在 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;
});