我使用rxjs的Observable与可通过HTTP访问的设备进行通信。 HTTP调用在设备完全联机之前启动,因此一些调用可能在开始时失败。在某些时候,设备处于联机状态,启动更新并定期轮询进度。在更新结束时,设备必须重新启动,然后在不同的URL上提供进度。
现在我想用rxjs映射此行为:
successfulCall: boolean = false;
testGet() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.url))
.map(response => {
let result: string = String.fromCharCode.apply(null, new Uint16Array(response.arrayBuffer()));
this.successfulCall = true;
return result;
})
.timeout(2000)
.retryWhen(errors => {
if (this.successfulCall) {
return Observable.throw("offline");
}
else {
return errors.delay(2000);
}
})
.onErrorResumeNext(this.observableTwo);
我的想法是使用retryWhen
作为开关,然后可以选择其他可观察对象。但是第二个可观测量从未开始,只有第一个被调用。根据设备状态(在线或离线),我会收到超时或有效的答案,然后呼叫继续。我也知道正常控制流程中的异常并不是一个非常好的想法。
我制作了一个流程图来形象化我的想法,因为我可以想象我对问题的描述可能会变得复杂。
wasSuccessful必须用false初始化,并且不显示可观察结果的处理
其他(可能更漂亮/更好)的方法也完全没问题,我只想解决问题而不必坚持我的approch。
答案 0 :(得分:0)
因此,您希望轮询远程设备,直到它联机并且在初始启动成功后继续更新过程,之后它将脱机,并且您希望再次开始轮询。
// mock implementation of polling until succes
var attempts = 0;
function startUp() {
attempts++;
if(attempts < 10) {
return Rx.Observable.throw(new Error('NOT BOOTED YET'));
}
attempts = 0;
return Rx.Observable.of('remote device online');
}
const bootupPollingSource = Rx.Observable.of('')
.concatMap(_ =>
Rx.Observable.defer(() => startUp())
.do(null, err => console.log('[debug] bootup err:' + err.message))
.retryWhen(attempts => attempts.delay(100))
);
const regularOperationsSource = Rx.Observable.from(['starting update','...','...'])
.concat(Rx.Observable.throw(new Error('device is rebooting')))
.catch(err => bootupPollingSource)
bootupPollingSource
.concat(regularOperationsSource)
.subscribe(console.log, console.log, () => console.log('completed'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.3/Rx.js"></script>
&#13;