免责声明:这是之前Safe update for 2 dependent streams问题的延续
处理允许流不终止的RxJS(或任何其他RX实现)中的错误的惯用方法是什么?
相关代码是
function convert(unit, value) {
var request = {};
request[unit] = value;
var conversion = $.ajax({
method: 'POST',
url: './convert.php',
data: request,
dataType: 'json'
}).promise();
return Rx.Observable.fromPromise(conversion).takeUntil(inInput.merge(cmInput));
}
var cmElement = document.getElementById('cm'),
inElement = document.getElementById('in');
var cmInput = Rx.Observable.fromEvent(cmElement, 'input').map(targetValue),
inInput = Rx.Observable.fromEvent(inElement, 'input').map(targetValue);
var inches = cmInput
.flatMap(convert.bind(null, 'cm'))
.startWith(0);
var centimeters = inInput
.flatMap(convert.bind(null, 'in'))
.startWith(0);
因此,您可以看到我们使用输入字段更改流并将其传递给convert函数,该函数将其转换为另一个单元并进一步传递结果.
如果在$.ajax()调用期间发生错误,那么它会向上传播并且整个英寸或高度流停止(实际上是预期的).
但是如何实现它呢?
这样我就可以优雅地处理错误,比如显示错误消息,并在新数据到达时再试一次?
我目前的想法是引入一个像Haskell的Data.Either这样的复合类型,并将其流式传输而不是标量双精度型.
思考?
UPD:是的,我读过Handling Exceptions in Reactive Extensions without stopping sequence,但我仍然希望有更好的方法.
解决方法:
你真的有两个选择:
>正如你所说,返回某种形式的可能是结果或错误.
由于这是JavaScript,您显然不需要正式类型,只能将错误实例与数字一起流式传输,并且您的订阅者可以通过检查接收到的值的运行时类型来告知它们何时接收它们.所以这就像在.fromPromise调用之后添加.catch(function(e){return Rx.Observable.of(e);}一样简单(或者代替.promise(),使用带有错误过滤器的.then()产生一个承诺,当出现错误时,它将具有您想要的任何值.
>在单独的流中发送错误.
基本上有转换需要另一个参数,它应该用来发出错误的观察者:
function convert(errorObserver, unit, value) {
...
return Rx.Observable
.fromPromise(conversion)
.catch(function (e) {
errorObserver.onNext(e); // or whatever you want to emit here
return Rx.Observable.empty(); // or possibly Rx.Observable.of(0) to reset?
})
...
}
然后只需为您的错误流创建一个Subject,并将其作为第一个转换参数提供.如果您希望将cm错误与错误分开,则创建2个主题.
我个人倾向于使用第一种方法.