Angular2 2.0.0-beta.15,Rxjs 5.0.0-beta.2
我有两个简单的rxjs observable,一个是共享的,一个不是(.share()在它上面调用)
我有一个angular2组件,它既可以订阅这两个observable,也可以在其模板中显示这些值,该模板还使用异步管道订阅了observable。
我单击一个按钮,在两个带有一些垃圾的observable上设置.next()。
模板会更新并显示每个模板的最新值。 组件中的订阅功能不会为非共享的observable触发。为什么呢?
plunkr: https://plnkr.co/edit/IIWvnTT1zLit1eUNknkk?p=preview
@Component({
selector: 'my-app',
template: `
<div>
<div>obs1 value: {{ observable1 | async }}</div>
<div>obs2 value: {{ observable2 | async }}</div>
<button (click)="randomizeIt()">randomize it</button>
<br>
<h3>Question 1</h3>
Why is obs1's initial value (from startWith) not displayed?
<h3>Question 2</h3>
Why does our subscription to obs2 never fire on new values?<br>
check console.log to see what i mean.
</div>`,
})
export class App {
public observable1:Observable<string>;
public observer1:any;
public observable2:Observable<string>;
public observer2:any;
constructor() {
this.observable1 = Observable.create(observer => {
this.observer1 = observer;
}).startWith("initial obs 1 value").share();
this.observable1.subscribe((val) => {
console.log('YOU WILL SEE THIS:', val);
})
this.observable2 = Observable.create(observer => {
this.observer2 = observer;
}).startWith("initial obs 2 value"); // no share!
this.observable2.subscribe((val) => {
console.log('WHY DOES THIS NEVER FIRE ON NEW VALUES?:', val);
})
}
public randomizeIt() {
let r = Math.random();
console.log('set both obs to: ', r);
this.observer1.next(r);
this.observer2.next(r);
}
}
提前致谢!
答案 0 :(得分:7)
Q1。 为什么没有显示obs1的初始值(来自startWith)?
来自share()文档:
返回一个可观察序列,该序列共享对基础序列的单个订阅。
这意味着,在您的情况下,{{ observable1 | async }}
和this.observable1.subscribe(....)
共享相同的订阅,当您在构造函数中订阅observable1
时,您已经启动了序列。初始化视图时,已启动observable1
的订阅并发出第一个值。因此async
会调用subscribe()
,但不会获得序列的第一个发射。
因此,如果您将订阅移至ngAfterViewInit()
内,则初始值将转至async
订阅。
ngAfterViewInit(){
this.observable1.subscribe((val) => {
console.log('YOU WILL SEE THIS CHANGE:', val);
})
}
Q2。 为什么我们对obs2的订阅从未触发新值?
每次订阅冷 Observable时,实际上都会创建一个新的Observable实例。创建新实例时,还会创建一个新的观察者实例。因此,您对构造函数的订阅是可观察的instance1
和观察者instance1
,而async
的订阅是可观察的instance2
和观察者instance2
。因此,当您致电randomizeIt()
时,请致电observer2
instance2
,该instance2
与async
订阅的可观察let obs = Observable.create(observer => {
this.observer2 = observer;
}).startWith("initial obs 2 value");
this.observable2 = obs.publish();
this.observable2.subscribe((val) => {
console.log('WHY DOES THIS NEVER FIRE?:', val);
})
this.observable2.connect();
绑定。
让你的观察“热”:
this.observable3 = Observable.create(observer => {
observer.next(Math.random());
});
<强>更新强>
假设您有一个可观察到的随机值:
this.observable3
现在,每次订阅SELECT
product,
COUNT(OrderNumber) AS CountOf
FROM
orders
WHERE
STATUS = 'booking' AND
YEAR(orderdate) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(orderdate) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
GROUP BY
product
ORDER BY CountOf DESC
时,您都会获得一个新的随机值。每个订户的价值不同。因为每个订户都有一个新实例。
来自文档:
将寒冷和热的Observable视为可以观看的电影或表演(“订阅”)会有所帮助。
冷可观察者:电影 Hot Observables :现场表演。
Hot Observables重播:视频中录制的现场表演。每当您观看电影时,即使所有电影观察者都看到相同的效果,您的电影也会独立于其他任何人的电影。另一方面,多个观看者共享现场表演。如果你迟到现场表演,你会错过一些。但是,如果它是在视频上录制的(在RxJS中,这将发生在BehaviorSubject或ReplaySubject上),您可以观看现场表演的“电影”。 .publish()。refCount()现场表演是艺术家在没人观看时放弃播放的表演,并且当观众中至少有一个人开始播放时。