2016-04-14 42 views
1

Angular2 2.0.0 beta.15,Rxjs 5.0.0-beta.2angular2 rxjs共享认购不点火

我有两个简单的rxjs观测,一个共享的,一个不叫就可以了(.share() )

我有一个angular2组件,它订阅了两个observables,并在其模板中显示值,该模板也用异步管道预订了observables。

我点击一个按钮来设置.next()两个observables与一些垃圾。

该模板更新并显示每个的最新值。 组件中的订阅函数不会为非共享的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); 
    } 

} 

提前感谢!

回答

6

Q1。 为什么obs1的初始值(from 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实例。当你创建一个新的实例时,你也创建一个新的观察者实例。因此,您对构造函数的订阅是可观察到的instance1和观察者instance1以及async的订阅是可观察到的instance2和观察者instance2。因此,当您拨打randomizeIt()时,您可以拨打observer2instance2,该号码必须通过登录async订阅可观察到的instance2

为了让您观察到的 “热”:

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你会得到一个新的随机值。每个用户的价值不一样。因为每个用户都有一个新的实例。

从文档:

它有助于觉得冷和热的观测量的电影或表演,人们可以观看(“订阅”)。

冷观察:电影。
Hot Observables:现场表演。
重播的热点观察对象:录制在视频上的现场表演。

每当您观看电影时,即使所有电影观众看到相同的效果,您的电影运行都与其他人的运行无关。另一方面,现场表演分享给多个观众。如果你迟到现场表演,你会错过一些。但是,如果它是录制在视频上的(在RxJS中这会发生在BehaviorSubject或ReplaySubject中),您可以观看现场表演的“电影”。 .publish()。refCount()现场表演是艺术家在没有人观看时退出播放的场景,并且在观众中至少有一个人时再次开始播放。

+0

谢谢!我明白Q1的答案。但我还不明白Q2。我注意到如果我删除{{observable2 |异步}},我的observer2订阅将随机randomItIt。完全需要更多的咖啡 –

+1

@ user2073082,因为当你删除'{{observable2 | async}}'只有一个'observable2'的实例。换句话说,你只调用一次'this.observable2.subscribe()'。因此,您只有一个该Observable的实例。 – Abdulrahman

+0

@ user2073082检查[this plunker](https://plnkr.co/edit/u1ddd4ZQCEzjTLElTs1Q?p=preview)。 'observable2'将会发出一个随机值。因为该Observable有两个实例。 '{{observable2 | async}}'与日志中的不同。 – Abdulrahman