我有一段代码我想定期执行,直到所有订阅者都取消订阅。
// 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());
我的预期输出看起来像那样:
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>
我在做设计错误吗?有没有办法做到这一点?
答案 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());