用于梳理算子的反应模式,其中一个依赖于另一个

时间:2016-12-18 16:18:57

标签: operators rxjs reactive-programming rx-swift

我有一个使用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中实现。

2 个答案:

答案 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/