为每个订阅者评估的 rxjs 地图运算符

rxjs map operator evaluated for each subscriber

为什么地图运算符是针对每个订阅者而不是一次评估的?

const obs1 = Rx.Observable.interval(1000).take(1).map((x, i) => {
  console.log(i+1 + ':1 map')
  return 'obs1';
})

const obs2 = Rx.Observable.interval(1300).take(1).map((x, i) => {
  console.log(i+1 + ':2 map')
  return 'obs2';
})

const obs3 = Rx.Observable.interval(1700).take(2).map((x, i) => {
  console.log(i+1 + ':3 map')
  return 'obs3';
})

const view = obs1.combineLatest(obs2, obs3, (obs1, obs2, obs3) => {                 return obs1 + ', ' + obs2 + ', ' + obs3; });

// Every subscriber adds more calls to map - why is it called multiple     times at the same time ?

view.subscribe((value) => {
  console.log('sub1: ' + value)
});

view.subscribe((value) => {
  console.log('sub2: ' + value)
});

view.subscribe((value) => {
  console.log('sub3: ' + value)
});

我在这里创建了一个测试用例:http://jsbin.com/jubinuf/3/edit?js,console

我可以用不同的方式编写这个测试用例来避免这种行为吗?

每个订阅者都会 运行 通过 Observable 序列。如果您希望每个人都获得结果流,请使用 .publish().refCount().

http://jsbin.com/ditikonopi/edit?js,console

只要至少有一个订阅,.publish() will return an observable sequence that shares a single subscription to the underlying sequence. refCount() 就会保持与来源的连接。

凯尔回答正确。 publish().refCount() 应用于所有三个 observable 将导致 map 选择器函数不会被重新执行。

为了更详细地说明该答案,了解使用 Rxjs 时冷热可观察对象之间的区别很有用。在你的例子中,你所有的可观察对象 obsX 都是冷的,所以它们是 'restarted' 订阅。 combineLatest 在幕后订阅了所有 3 个,这就是 map 被重新执行的原因。查看 以获得插图说明。对于初学者来说,这是一个常见的绊脚石,但它很容易理解。