为什么在订阅产生价值后调用max和min?

时间:2015-04-30 13:52:37

标签: javascript rxjs

我有一组对象,在处理集合中的任何项目之前,我需要知道数字范围是什么。我想出了类似于下面的代码,似乎给出了正确的答案:

var arr = Rx.Observable.fromArray([10,-10,4,-5,20,4,7]),
//In actual code this is an array of objects, so have a custom compare function
numberComparer = function(a,b) { return a-b; };

//In actual code this is prefixed by a filter and mapping operation 
arr.flatMap(function(x) {
    return Rx.Observable.zip(
        arr.max(numberComparer), 
        arr.min(numberComparer), 
        function(max, min) { 
            return { 
                stats: {max: max, min: min}, 
                item: x
            };
        }
    );
})
.subscribe(function(item) { 
    DoStuffWithItem(item.item, item.stats); 
});

但我对幕后发生的事情感到有些困惑。当第一项产生于订阅方法时,比较器函数给出了正确的答案,但随后它们继续在项目产量之间被调用。

这是JSBin showing what I mean。我在这里做错了吗?是否有更好,更Rx-y的方式来做到这一点?我期望发生的是首先计算最大值和最小值,然后调用订阅函数而不调用max或min。

编辑:看起来行为可能是因为它已经输出的内容不断重新比较,这部分解释了为什么我会看到这种行为。我只是不明白它为什么这样做(以及如何让它停止):)

1 个答案:

答案 0 :(得分:1)

你的第二个例子是在正确的轨道上。我建议使用when() andthenDo,但它应该具有相同的行为,但您可以更清楚地传达您的意图,而您不必担心同步

    var minMax = Rx.Observable.when(
    filteredArray.max().and(filteredArray.min())
    .thenDo(function(x, y) { 
      return { max : x, min : y};
    }));

    minMax.flatMap(function() {
          return filteredArray;
    }, function(stats, x) {
          return {stats : stats, value : x};
    });

以下是该示例的modifed version

由于这不是计算minMax的最有效方法,因为您在阵列中运行两次,因此可以通过使用reduce()创建自己的minMax运算符来进一步优化。

Rx.Observable.prototype.minMax = function(comparer) {

  var source = this,
      c = comparer || function(x, y) {
    return x - y;
  };


  return source.reduce(function(seed, x) {

     if (c(x, seed.min) < 0) (seed.min = x);
     if (c(x, seed.max) > 0) (seed.max = x);

    return seed;

  }, {min : Number.MAX_VALUE, max : Number.MIN_VALUE });

};