在至少一次成功响应之后错误交换到另一个observable

时间:2016-11-10 13:10:57

标签: typescript rxjs observable rxjs5

我使用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初始化,并且不显示可观察结果的处理

Flowchart of Observable

其他(可能更漂亮/更好)的方法也完全没问题,我只想解决问题而不必坚持我的approch。

1 个答案:

答案 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;
&#13;
&#13;