forEach运算符未经订阅而被评估

时间:2016-10-10 02:00:19

标签: javascript functional-programming rxjs frp rxjs5

我试图教自己一些反应性函数式编程。 Ben Lesh的video显示了一个可观察的例子。我之前的阅读表明,一个可观察者是懒惰的,即它只在订阅后进行评估。奇怪的是,这段代码并不需要订阅才能打印到控制台。

var Rx = require('rxjs/Rx')

var source = Rx.Observable.from([1,2,3,4,5]);

var newSource = source.filter(x => x % 2 === 1)
                .map(x => x + '!')
                .forEach(x => console.log(x));

来自RxJS docs

似乎Observable必须积极地解决.forEach发出的承诺,我对此感到困惑。

此代码引发了进一步的混淆:

var Rx = require('rxjs/Rx')

var source = Rx.Observable.from([1,2,3,4,5]);

var newSource = source.filter(x => x % 2 === 1)
      .map(x => x + '!')
      .do(x => console.log(x));

在运行newSource.subscribe();之前不会评估,请帮我解释两个运营商背后的差异。

1 个答案:

答案 0 :(得分:2)

默认情况下,Observable是懒惰的。如果你在一个observable上执行一个操作符,rxjs会为你创建一个与前一个相关联的新observable。知道可观察量是不可改变的。

然而,ForEach是一种特殊的运营商。它不会返回一个新的Observable,但它会订阅引擎盖下的observable并对该observable发出的每个元素执行一个函数。如果你检查forEach实现的源代码,它在Observable类本身上,你会看到以下内容(只是一个片段)。

const subscription = this.subscribe((value) => {
    if (subscription) {
      // if there is a subscription, then we can surmise
      // the next handling is asynchronous. Any errors thrown
      // need to be rejected explicitly and unsubscribe must be
      // called manually
      try {
        next(value);
      } catch (err) {
        reject(err);
        subscription.unsubscribe();
      }

在这里我们可以看到observable正在订阅,价值是'next'-ed。下一个函数是传递给forEach调用的函数。