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

Javascript 为什么在订阅产生值后调用max和min?,javascript,rxjs,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

我有一个对象集合,在处理集合中的任何项目之前,我需要知道其数量范围。我提出了与下面类似的代码,它似乎给出了正确的答案:

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); 
});
但我对幕后发生的事情有点困惑。当第一个项目被提交给subscribe方法时,comparer函数给出了正确的答案,但是在项目之间继续调用它们

这是一本书。我做错什么了吗?有没有更好的,更Rx-y的方法来做到这一点?我所期望的是首先计算max和min值,然后调用subscription函数,而不调用max或min


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

你的第二个例子是正确的。我建议使用
when()
以及
然后执行
,但是,它应该具有相同的行为,但是您可以更清楚地传达您的意图,并且不必担心同步问题

    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};
    });
下面是一个例子

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

Rx.Observable.prototype.minMax=函数(比较器){
var source=这个,
c=比较器| |函数(x,y){
返回x-y;
};
返回源.reduce(函数(seed,x){
如果(c(x,seed.min)<0(seed.min=x);
如果(c(x,seed.max)>0(seed.max=x);
返回种子;
},{min:Number.MAX_值,MAX:Number.min_值});
};

Hmm,因为您使用的是
flatMap
zip
操作符的调用次数将是集合中元素数的倍。我不知道您想如何使用此代码,但也许
combinelateest
可以完成此工作?我们正在进行一个可视化,它将获取每个项目,并根据其在整个集合中的位置对其进行分类,以便在传递值的同时传递最小值/最大值。我对您的示例进行了一些调整,以使其以这种方式工作,但仍不确定这是否比计算RX链的最小/最大值,然后将其传递进来“更好”。谢谢你,这也解决了我所关心的一个问题,那就是在整个列表中迭代两次,分别得到最大值和最小值。看起来不错!
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 });

};