angular2 rxjs共享订阅未触发

时间:2016-04-14 13:08:09

标签: angular rxjs

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);
    }   

}

提前致谢!

1 个答案:

答案 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,该instance2async订阅的可观察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()现场表演是艺术家在没人观看时放弃播放的表演,并且当观众中至少有一个人开始播放时。