使用多个订阅者

时间:2018-05-15 15:03:08

标签: javascript rxjs observable

我有一段代码我想定期执行,直到所有订阅者都取消订阅。

// This function shall be called *once* per tick,
// no matter the quantity of subscriber.
function doSomething(val) {
    console.log("doing something");
    return val;
}

observable = Rx.Observable.timer(0, 1000).map(val => doSomething(val));

const first = observable.subscribe(val => console.log("first:", val));
const second = observable.subscribe(val => console.log("second:", val));

// After 1.5 seconds, stop first.
Rx.Observable.timer(1500).subscribe(_ => first.unsubscribe());
// After 2.5 seconds, stop second.
Rx.Observable.timer(2500).subscribe(_ => second.unsubscribe());

JSFiddle

我的预期输出看起来像那样:

doing something
first: 0
second: 0
doing something
first: 1
second: 1
doing something
second: 2
<nothing more>

然而,当调用两个observable时,doSomething函数被调用两次。这是实际输出:

doing something
first: 0
doing something
second: 0
doing something
first: 1
doing something
second: 1
doing something
second: 2
<nothing more>

我在做设计错误吗?有没有办法做到这一点?

2 个答案:

答案 0 :(得分:5)

您看到的行为是正确的。 interval返回的可观测量很冷。也就是说,在观察者订阅之前不会创建计时器,并且当一个人执行时,创建的计时器专门用于该订阅。

您期望的行为可以使用share运算符实现:

observable = Rx.Observable
  .timer(0, 1000)
  .map(val => doSomething(val))
  .share();

share运算符引用计数订阅并将源可观察多播到多个订阅者 - 因此在两个订阅者之间只共享一个间隔/计时器。

有关详细信息,您可能会发现this article有用。

答案 1 :(得分:0)

Live working example。 然后你需要使用Subjects。 Plain Observables是单播的(这意味着每个订阅者拥有Observable的独立执行权)。这就是每个观察者被称为所有执行链的方式。

observable = Rx.Observable.timer(0, 1000)
  .map(val => doSomething(val));
每个观察者都会调用

map

Subjects是一种特殊类型的Observable,允许值进行多播,这意味着您共享Observable的单行执行。这是一个rxjs6,如果你迷失了可管道运算符please take a look here

首先,获取imports

import { Observable, Subject, timer } from 'rxjs';
import { map, share } from 'rxjs/operators';

然后你有,

const subject = new Subject();

const doSomething = val => {
  console.log("doing something");
  return val;
}

const observable = timer(0, 1000).pipe(
  map(val => doSomething(val)),
).pipe(share());

const first = observable.subscribe(val => console.log("first:", val));
const second = observable.subscribe(val => console.log("second:", val));
const tercer = observable.subscribe(val => console.log("tercer:", val));

// After 1.5 seconds, stop first.
timer(1500).subscribe(_ => first.unsubscribe());
// After 2.5 seconds, stop second.
timer(2500).subscribe(_ => second.unsubscribe());
// After 2.5 seconds, stop second.
timer(2500).subscribe(_ => tercer.unsubscribe());