【问题标题】:What's difference between "reduce" and "scan"“减少”和“扫描”有什么区别
【发布时间】:2019-04-28 23:14:08
【问题描述】:

我正在研究 RXJS 并遇到了一个问题:带有运算符“reduce”和“scan”的相同代码以不同的方式工作,但我认为必须返回相同的结果。 下面的例子。 请帮忙。

const txtElement1 = document.getElementById('txt1');
const txtElement2 = document.getElementById('txt2');
const txtElement3 = document.getElementById('txt3');

// function return Observable
function get(array, initValue) {
  return Rx.Observable.create(observer => {
    let timer = initValue;

    array.forEach(item => {
      setTimeout(() => observer.next(item), timer);
      timer += 1000;
    });
  });
}

// 1) don't work with "reduce"
var stream1$ = get(['John', 'Ann', 'Bob'])
  .reduce(function(acc, x) {
    return acc + ` ${x}`;
  }, 'first - ');

stream1$.subscribe(text => txtElement1.innerHTML = text);

// 2)  the same code, but with "scan" - working
var stream2$ = get(['John', 'Ann', 'Bob'])
  .scan(function(acc, x) {
    return acc + ` ${x}`;
  }, 'second - ');

stream2$.subscribe(text => txtElement2.innerHTML = text);

// 3)  and the simple Observable with "reduce" - working
var stream3$ = Rx.Observable.from(['John', 'Ann', 'Bob'])
  .reduce(function(acc, x) {
    return acc + ` ${x}`;
  }, 'third - ');

stream3$.subscribe(text => txtElement3.innerHTML = text);

【问题讨论】:

  • 如果它和其他语言一样,scanreduce 做同样的事情,除了它返回所有中间累加器而不是最后一个。文档应该能够为您解答这个问题。
  • 我不认为 StackOverflow 仅适用于其他任何地方都找不到的信息。
  • @Carcigenicate 我并没有说它们工作相同。我说我期待同样的结果。例如,第三个示例对两个运算符的工作方式相同。但第一个不是。区别仅在于函数“setTimeout”。不幸的是,文档没有说明任何内容。
  • reduce 运算符仅在其源 observable 完成时才发出一个值。第一个示例中的 Observable 不完整,这就是原因。尝试将observer.complete() 添加到get 返回的observable。

标签: javascript rxjs


【解决方案1】:

来自 RxJS 文档,

扫描

对 Observable 发出的每个项目依次应用一个函数, 并发出每个连续的值

减少

对 Observable 发出的每个项目依次应用一个函数, 并发出最终值

示例代码

扫描

var source = Rx.Observable.range(1, 3)
.scan(
    function (acc, x) {
        return acc + x;
    });

var subscription = source.subscribe(
    function (x) { console.log('Next: ' + x); },
    function (err) { console.log('Error: ' + err); },
    function () { console.log('Completed'); });

对于Observable发出的每个值,scan依次发出对应的输出,所以Output会有3个值,范围为1到3,如下

Output
Next: 1
Next: 3
Next: 6
Completed

减少

var source = Rx.Observable.range(1, 3)
    .reduce(function (acc, x) {
        return acc * x;
    }, 1)

var subscription = source.subscribe(
    function (x) { console.log('Next: ' + x); },
    function (err) { console.log('Error: ' + err); },
    function () { console.log('Completed'); });

Reduce 函数将值从 observables 减少为单个值(最终结果)并发出。所以输出会如下,

Next: 6
Completed

【讨论】:

    【解决方案2】:

    几乎相同,但 scan 每次迭代都会发出。而 reduce 只是发出最终结果。当我想真正了解 reduce 正在做什么时,我喜欢扫描。所以有时我。使用reduce,我无法想象reduce 实际在做什么。在这种情况下,我简单地将 reduce 换成 scan,因为它会在每次迭代时发出。这样我可以放入一个日志语句并查看每次迭代的结果。

    【讨论】:

      【解决方案3】:

      Rx.scan 是连续的,而 reduce 不是连续的。

      【讨论】:

        猜你喜欢
        • 2011-08-22
        • 2010-09-06
        • 1970-01-01
        • 2018-06-18
        • 1970-01-01
        • 1970-01-01
        • 2010-09-29
        • 2011-12-21
        • 2017-04-29
        相关资源
        最近更新 更多