我有一个用户编程方案,其中用户可以结束了创建依赖于彼此的两个观测。 RxJS不允许循环依赖关系,据我所看到的,内存或堆达到其极限和onError
回调被触发,其值为true
。
如何检测循环依赖明确,并抛出一个更具描述性错误消息?
此代码演示了如何创建一个RxJS循环依赖:
var obsA, obsB; obsA = Rx.Observable .returnValue(42) .combineLatest(obsB, function (a, b) { return a + b; }); obsB = Rx.Observable .returnValue(42) .combineLatest(obsA, function (b, a) { return b + a; }); obsA .subscribe(function (val) { console.log('onNext:' + val); }, function (err) { console.error('onError: ' + err); }, function () { console.log('onCompleted'); });
该错误消息简直是true
。
在原来的问题的代码不会创建一个循环依赖。 在您指定的时间ObsA
, ObsB
是undefined
,还等什么你真的做的是调用combineLatest(undefined, function ...)
所以你看到的错误是因为你传递undefined
到combinedLatest()
实际上,它需要一些努力,创造一个真正的循环依赖。 如果您使用的defer
,那么你将有一个真正的循环依赖关系:
var obsA, obsB, aRef, bRef; aRef = Rx.Observable.defer(function () { return obsA; }); bRef = Rx.Observable.defer(function () { return obsB; }); obsA = Rx.Observable .returnValue(42) .combineLatest(bRef, function (a, b) { return a + b; }); obsB = Rx.Observable .returnValue(42) .combineLatest(aRef, function (b, a) { return b + a; }); obsA.subscribe();
<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>
现在是一个真正的循环依赖。 不幸的是,你仍然得到同样的错误,但有一个更深刻的堆栈跟踪:
RangeError: Maximum call stack size exceeded.
/* ... stack ... */
没有万无一失的方法来检测周期。 你可以换一个新的可观测的观测和检测到你的订阅方法递归调用。 但是,这样的算法会如果标的观测使用被打败subscribeOn
或publish
或concat
其他任何延迟实际圆形订阅。
最好的建议,我已经是追加一个catch
用于检查各种错误,并有更好的错误替换它条款:
var obsA, obsB, aRef, bRef; aRef = Rx.Observable.defer(function () { return obsA; }); bRef = Rx.Observable.defer(function () { return obsB; }); obsA = Rx.Observable .returnValue(42) .combineLatest(bRef, function (a, b) { return a + b; }) .catch(function (e) { var isStackError = e instanceof RangeError && e.message === 'Maximum call stack size exceeded'; return Rx.Observable.throw(isStackError ? new Error('Invalid, possibly circular observables.') : e); }); obsB = Rx.Observable .returnValue(42) .combineLatest(aRef, function (b, a) { return b + a; }) .catch(function (e) { var isStackError = e instanceof RangeError && e.message === 'Maximum call stack size exceeded'; return Rx.Observable.throw(isStackError ? new Error('Invalid, possibly circular observables.') : e); }); obsA.subscribe();
<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>