我有一个使用REST服务的应用程序。它每次都会发出请求,例如点击一个按钮。但是,它需要先获取令牌,然后每隔20分钟刷新一次。这是一个大理石图,表示所需的流组合......
TOKEN SOURCE ---------A--------------B--------------C----------------D-
REQUEST SOURCE ----1-----------2--3---------4-----------5-------6--------
RESULT SOURCE ---------A1-----A2-A3--------B4----------C5------C6-------
通常,请求源会触发与令牌源的最新值组合的结果,但是在令牌流上没有发出任何项时会出现异常 - 在这种情况下,请求会被缓冲,直到第一个令牌到达为止然后发送。
combineLatest
运算符几乎就在那里,但它会在任一流发出时触发。 sample
运算符的大理石图也似乎很接近,但它根据时间间隔限制输出,这不是我想要的。
哪个运营商/运营商链适用于此实例?
我使用RxJS进行原型设计,但我需要在RxSwift中实现。
答案 0 :(得分:2)
你接近解决方案。重要的细节是Source(2)投影其所有元素,而Source(1)不直接投影,只有Source(1)更改时,拥有额外的信息可以帮助我们丢弃。
s1.combineLatest(s2, (a, b) => [a, b])
.distinctUntilChanged(v => v[1])
这是测试设置:
var s1 = Rx.Observable.interval(997).take(10).map(i => String.fromCharCode(65 + i))
var s2 = Rx.Observable.interval(251).take(10).delay(500).skip(1)
s1.combineLatest(s2, (a, b) => [a, b])
.distinctUntilChanged(v => v[1])
.subscribe(value => console.log(value))
输出:
[" A",1] [" A",2] [" A",3] [" A",4] [" B",5] [" B",6] [" B",7] [" B",8] [" C",9]
答案 1 :(得分:1)
由于您希望仅根据REQUEST SOURCE
触发数据发布,因此它可能是启动流然后切换的最佳方式 - 或者在这种情况下flatMap
- 进入TOKEN SOURCE
并将这两者结合起来 - 不需要高级操作员:
(注意:我的假设是,您的TOKEN SOURCE
会重播最新的令牌:
var token$ = Rx.Observable.interval(1000).take(10).map(() => Math.random()).publishReplay(1); // simulating the token source: new token every second and replaying the latest token
var requests$ = Rx.Observable.interval(250).take(10); // simulating the request source: emitting a new request every 250ms
token$.connect();
requests$
.flatMap(request => token$
.take(1)
.map(token => ({request, token}))
)
.subscribe(function(requestWithToken) {
console.log("Matched: ", requestWithToken);
});
您可以在此处查看实时小提琴:https://jsfiddle.net/rn8rzufg/