Rx扩展 - 使用延迟以避免执行不必要的可观察对象的正确方法?

时间:2015-11-24 17:08:50

标签: coffeescript reactive-programming rxjs

我正在尝试使用delay和amb来执行由时间分隔的相同任务的序列。 我想要的是下载尝试在将来某个时间执行,只有在过去之前相同的任务失败。这就是我设置的方式,但不像我期望的那样,所有这三个下载似乎都会毫不拖延地执行。

    Observable.amb([
        Observable.catch(redditPageStream, Observable.empty()).delay(0 * 1000),
        Observable.catch(redditPageStream, Observable.empty()).delay(30 * 1000),
        Observable.catch(redditPageStream, Observable.empty()).delay(90 * 1000),
        # Observable.throw(new Error('Failed to retrieve reddit page content')).delay(10000)
        # Observable.create(
            # (observer) ->
                # throw new Error('Failed to retrieve reddit page content')
        # )

    ]).defaultIfEmpty(Observable.throw(new Error('Failed to retrieve reddit page content')))

完整代码可以在这里找到。 src

我希望第一个成功的观察者会取消那些仍在延迟的观察者。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

delay实际上并没有停止执行你正在做的事情只是在事件传播时出现延迟。如果你想延迟执行,你需要做类似的事情:

redditPageStream.delaySubscription(1000)

由于您的源代码正在立即生成,因此上述内容将延迟实际订阅基础流,以便在开始生成时有效延迟。

我建议您尽管使用其中一个retry运算符来处理retry逻辑,而不是通过amb运算符滚动自己。

redditPageStream.delaySubscription(1000).retry(3);

会给你一个恒定的重试延迟,但是如果你想实现线性退避方法,你可以使用retryWhen()运算符,这样你就可以将任何你想要的逻辑应用到退避。

redditPageStream.retryWhen(errors => {
  return errors
          //Only take 3 errors
          .take(3)
          //Use timer to implement a linear back off and flatten it
          .flatMap((e, i) => Rx.Observable.timer(i * 30 * 1000));
});

基本上retryWhen将创建一个Observable of errors,将通过它的每个事件视为重试尝试。如果您输入错误或完成流,则会停止重试。