2014-09-02 28 views
2

在我的系统中,我有一个源代码,两个“步骤”将源映射到一个新值,然后结合这两个步骤来创建最终值。通过该系统的初始运行工程,我希望,产生3如何同步RxJS更新以使中间值不通过流?

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.onNext(1); 

> calc sum: 4 
> calc sum: 5 

首先是一个中间结果...作为新的源值通过该系统的一个组成部分,然后我得到时所有的值已经完成传播的最终结果。

所以我的问题是,什么是推荐的方式来配置的东西,使新的价值推入源将通过系统原子通过,只产生一个总和结果?

谢谢!

回答

1

这就是combineLatest的工作方式,它确实令人困惑,因为它允许您指出的这些暂时不一致的状态。从combineLatest学习的关键是它发出一个新的项目,只要其中一个源发出一个新项目,并且它部分地完成,它没有任何种类的“等待”机制。在图中,http://rxmarbles.com/#combineLatest

您可能需要的是zip运算符。 Zip等待其输入发出相互匹配的项目。换句话说,一旦来自所有输入的所有第n项已经发射,则zip的输出发出其第n项。它非常适用于您有source生成stepOnestepTwo并且您想要结合stepOnestepTwo的钻石套件。

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

请记住zip假设输入具有相同的发射频率。在其他情况下,如果排放的频率不同,您可能需要将stepOne中的项目与stepTwo组合在一起。那么你需要使用combineLatest

+0

感谢您的回答,并链接到http://rxmarbles.com。这非常有用,而且很有趣! – 2014-09-03 18:21:09

+1

更多阅读之后,我发现我可以使用Bacon.js和[无故障更新](https://github.com/baconjs/bacon.js/issues/272)特性后的行为。我不认为RxJS有支持,请有人纠正我,如果我错了。 – 2014-09-04 16:42:43

+0

RxJS不会,但是这并不阻止你完成你需要的任何事情。它将以不同的方式。 Zip是大多数情况下的解决方案。 Bacon.js的内存使用量也很大。 – 2014-09-04 18:10:08