5

在我的系统中,我有一个源,两个“步骤”将源映射到一个新值,然后是一个将这两个步骤组合起来以创建最终值的总和。这个系统的初始运行按我希望的那样工作,产生一个 3 的总和。

var source = new Rx.BehaviorSubject(0);    
var stepOne = source.map(function (value) {
    return value + 1;
});
var stepTwo = source.map(function (value) {
    return value + 2;
});    
var sum = Rx.Observable.combineLatest(
    stepOne,
    stepTwo,
    function (s1, s2) {
        console.log('calc sum: ' + (s1 + s2));
        return s1 + s2;
    }).subscribe(function (sum) {
    });

输出:

> calc sum: 3

但是,如果我为 source 输入一个新值,我会得到如下两个结果:

source.onNext(1);

> calc sum: 4
> calc sum: 5

第一个是中间结果……当新的源值通过系统的一部分时,当所有值都完成传播时,我得到最终结果。

所以我的问题是,推荐的配置方法是什么,以便推入源的新值将原子地通过系统并且只生成一个总和结果?

谢谢!

4

1 回答 1

1

这就是combineLatest工作原理,它确实令人困惑,因为它允许这些暂时不一致的状态,正如您所指出的那样。要学习的关键combineLatest是,只要它的任何一个源发出一个新项目,它就会发出一个新项目,而且它只是部分地这样做,它没有任何类型的“等待”机制。

在图表中,http://rxmarbles.com/#combineLatest

您可能想要的是zip操作员。Zip 等待其输入发出相互匹配的项目。换句话说,一旦所有输入中的所有第 n 项都已发出,zip 的输出就会发出第 n 项。它非常适合您source生成stepOneandstepTwo并且想要组合stepOneand的钻石盒stepTwo

在图表中,http://rxmarbles.com/#zip

请记住,zip假设输入具有相同的发射频率。在其他情况下,您可能希望将 stepOne 中的项目与 stepTwo 组合起来,因为它们具有不同的发射频率。然后你需要使用combineLatest.

于 2014-09-03T16:08:48.973 回答