我想使用angular-rx作为结果的简单刷新按钮。如果用户单击刷新按钮,则重新加载结果。如果用户在1秒内单击刷新按钮100次,则仅加载最新结果。如果结果由于某种原因失败,那并不意味着刷新按钮应该停止工作。
为了达到最后一点,我想保留订阅(或重新订阅),即使它失败了,但我无法弄清楚如何做到这一点?
这不起作用,但这是一个简单的例子,我尝试重新订阅错误:
var refreshObs = $scope.$createObservableFunction('refresh');
var doSubscribe = function () {
refreshObs
.select(function (x, idx, obs) {
// get the results.
// in here might throw an exception
})
.switch()
.subscribe(
function (x) { /*show the results*/ }, // on next
function (err) { // on error
doSubscribe(); // re-subscribe
},
function () { } // on complete
);
};
doSubscribe();
我认为这很常见,应该有一些标准的做法来实现这个目标吗?
使用建议的解决方案,这就是我所做的测试:
// using angularjs and the rx.lite.js library
var testCount = 0;
var obsSubject = new rx.Subject(); // note. rx is injected but is really Rx
$scope.refreshButton = function () { // click runs this
obsSubject.onNext();
};
obsSubject.map(function () {
testCount++;
if (testCount % 2 === 0) {
throw new Error("something to catch");
}
return 1;
})
.catch(function (e) {
return rx.Observable.return(1);
})
.subscribe(
function (x) {
// do something with results
});
这些是我的测试结果:
我的理解是catch应该保留订阅,但我的测试表明它没有。为什么呢?
答案 0 :(得分:5)
根据评论中给出的上下文,您需要:
你真的不需要重新订阅,它是一种反模式,因为Rx中的代码从不依赖于它,而额外的递归调用只会让读者感到困惑。它还提醒我们回调地狱。
在这种情况下,你应该:
select().switch()
替换为.flatMap()
(或.flatMapLatest()
)。当您执行select()
时,结果是元流(流的流),并且您正在使用switch()
将元数据流展平为流。这就是flatMap所做的一切,但仅限于一次操作。您还可以将flatMap理解为JS Promises的.then()
。.catch()
,如catch
块中所示。在发生错误后您无法获得更多结果的原因是,Observable始终会因错误或“完成”错误而终止。事件。使用catch()
运算符,我们可以用Observable上的sane事件替换错误,以便它可以继续。 改善您的代码:
var refreshObs = $scope.$createObservableFunction('refresh');
refreshObs
.flatMapLatest(function (x, idx, obs) {
// get the results.
// in here might throw an exception
// should return an Observable of the results
})
.catch(function(e) {
// do something with the error
return Rx.Observable.empty(); // replace the error with nothing
})
.subscribe(function (x) {
// on next
});
另请注意,我删除了onError和onComplete处理程序,因为它们内部没有任何操作。
另请参阅更多运营商。例如,retry()
可用于自动获得结果'每次发生错误时都会再次出现见https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/retry.md
将retry()
与do()
结合使用以处理错误(do
),并允许订阅者自动重新订阅源可观察量(retry
)。
refreshObs
.flatMapLatest(function (x, idx, obs) {
// get the results.
// in here might throw an exception
// should return an Observable of the results
})
.do(function(){}, // noop for onNext
function(e) {
// do something with the error
})
.retry()
.subscribe(function (x) {
// on next
});
请参阅此处的工作示例:http://jsfiddle.net/staltz/9wd13gp9/9/