Rx运算符以combineLatest开头,但后来就像withLatestFrom一样

时间:2017-02-03 02:07:23

标签: reactive-programming rx-swift reactivex

我正在寻找一个运算符,它结合了两个Observables,在Observables发出一个元素(类似于combineLatest)之前没有发出任何内容,但后来只通过组合元素发出元素来自一个Observable,其中Observable最近发出的元素(类似于withLatestFrom)。结果看起来像这样(y observable是“控件”):

enter image description here

这样的运营商是否存在?

2 个答案:

答案 0 :(得分:2)

我用Java解决了这个问题,但同样的理论应该对你有用。

你拥有的是两种基本模式; combineLatest值后跟withLatestFrom值。如果首先触发withLatestFrom,则您希望跳过combineLatest值。

首先制作withLatestFrom observable:

Observable<Result> wlf = o1.withLatestFrom(o2, f::apply);

接下来,我们要创建发出单个值的combineLatest observable。我们还希望在wlf触发时停止此观察:

Observable<Result> cl = Observable.combineLatest(o1, o2, f::apply)
    .take(1).takeUntil(wlf);

最后将这两个observable一起添加......为方便起见,我做了一个辅助方法来接受任何两个observable和一个双函数运算符:

public static <Result,
    Param1, Source1 extends Param1,
    Param2, Source2 extends Param2>
Observable<Result> combineThenLatestFrom(
    final Observable<Source1> o1,
    final Observable<Source2> o2,
    final BiFunction<Param1, Param2, Result> f
) {
    final Observable<Result> base = o1
        .withLatestFrom(o2, f::apply);
    return Observable
        .combineLatest(o1, o2, f::apply)
        .take(1).takeUntil(base)
        .mergeWith(base);
}

这是我用来验证方法的测试代码:

public static void main(final String[] args) {
    final TestScheduler scheduler = new TestScheduler();
    final TestSubject<String> o1 = TestSubject.create(scheduler);
    final TestSubject<String> o2 = TestSubject.create(scheduler);
    final Observable<String> r = combineThenLatestFrom(o1, o2, (a, b) -> a + b);
    r.subscribe(System.out::println);
    o1.onNext("1");
    o1.onNext("2");
    o2.onNext("A");
    o2.onNext("B");
    o2.onNext("C");
    o2.onNext("D");
    o1.onNext("3");
    o2.onNext("E");
    scheduler.triggerActions();
}

哪个输出:

2A
3D

答案 1 :(得分:0)

它很漂亮,但这有效(在C#中):

var xs = new Subject<string>();
var ys = new Subject<int>();

var query =
    Observable
        .Merge(
            xs.Select(x => new { xt = true, yt = false, x, y = default(int) }),
            ys.Select(y => new { xt = false, yt = true, x = default(string), y }))
        .StartWith(new { xt = false, yt = false, x = default(string), y = default(int) })
        .Scan((a, b) => new
        {
            xt = a.xt && a.yt ? false : a.xt || b.xt,
            yt = a.xt && a.yt ? false : a.yt || b.yt,
            x = b.xt ? b.x : a.x,
            y = b.yt ? b.y : a.y
        })
        .Where(z => z.xt & z.yt)
        .Select(z => z.y + z.x);

query.Subscribe(v => Console.WriteLine(v)); 

ys.OnNext(1);
ys.OnNext(2);
xs.OnNext("A");
xs.OnNext("B");
xs.OnNext("C");
xs.OnNext("D");
ys.OnNext(3);
xs.OnNext("E");

它给出了:

2A
3D