使用超时对轮询器进行建模的最佳方法是什么?某个条件导致提前退出为“反应流”?
e.g。
如果我有一个可观测值,每秒产生一个递减的正整数序列
9,8,7,6,5,4,3,2,1,0
编写消费者的最佳方法是在5秒后获取最新的单个事件,如果生成的时间超过超时,则为“0”事件。
这是我现在的代码:( Java中的示例)
int intialValue = 10;
AtomicInteger counter = new AtomicInteger(intialValue);
Integer val = Observable.interval(1, TimeUnit.SECONDS)
.map(tick -> counter.decrementAndGet())
.takeUntil(it -> it == 0)
.takeUntil(Observable.timer(5, TimeUnit.SECONDS))
.lastElement()
.blockingGet();
System.out.println(val);
如果initialValue = 10,我希望打印6。如果initialValue = 2,我希望在5秒超时到期之前打印0。
如果有更好的方法,我很感兴趣。
答案 0 :(得分:0)
我认为没有比你做得更好的方式。您必须具备以下条件:
interval
)scan
)takeWhile
)takeUntil(timer(...))
)last
)每个人都由一名运营商代表。你不可能做很多事情来解决这个问题。我使用了一些不同的运算符(scan
用于聚合,takeWhile
用于终止值)但是它的运算符数相同。
const { interval, timer } = rxjs;
const { scan, takeWhile, takeUntil, last, tap } = rxjs.operators;
function poll(start) {
console.log('start', start);
interval(1000).pipe(
scan((x) => x - 1, start),
takeWhile((x) => x >= 0),
takeUntil(timer(5000)),
tap((x) => { console.log('tap', x); }),
last()
).subscribe(
(x) => { console.log('next', x); },
(e) => { console.log('error', e); },
() => { console.log('complete'); }
);
}
poll(10);
setTimeout(() => { poll(2); }, 6000);

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.min.js"></script>
&#13;
我不清楚你希望它如何在边界上发挥作用。在你的例子中,你总是在发射之前递减,所以如果你的初始值是10,那么你发出9,8,7,6(4个值)。如果你想从10开始那么。您可以执行scan(..., start + 1)
,但这会在7结束,因为takeUntil(...)
中的计时器与源间隔对齐,因此将排除6。如果要发出5个值,则可以执行takeUntil(timer(5001))
。另外,如果您不想等一秒钟发出第一个值,那么您可以将startWith(start)
放在scan(...)
之后。或者您可以timer(0, 1000)
使用scan(..., start + 1)
代替源间隔。
另请注意,在生成无效值(takeWhile
)之前,值(-1
)的终止不会终止。所以它会在收到终止值(0
)后持续一秒钟。似乎大多数终止运算符都以这种方式工作,如果它们终止于某些值,那么它们就不会让其他运算符通过。
您可以执行take(5)
而不是takeUntil(timer(5000))
,因为您知道如果适用于您的方案,它会在匹配的时间间隔内触发。由于计时器排队,这也可以解决排除最后一个值的问题。