【问题标题】:angular2 rxjs shared subscribe not firingangular2 rxjs 共享订阅未触发
【发布时间】:2016-08-06 01:35:33
【问题描述】:

Angular2 2.0.0-beta.15,Rxjs 5.0.0-beta.2

我有两个简单的 rxjs observables,一个共享,一个不共享(.share() 调用它)

我有一个 angular2 组件,它订阅两个 observables 并在其模板中显示值,它还通过异步管道订阅 observables。

我点击一个按钮在两个 observables 上设置 .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);
    }   

}

提前致谢!

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    第一季度。 为什么不显示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);
        })
    }
    

    第二季度。 为什么我们订阅 obs2 永远不会触发新的价值观?

    每次订阅 cold Observable 时,实际上都会创建一个新的 Observable 实例。当你创建一个新实例时,你也创建了一个新的观察者实例。因此,您对构造函数的订阅是可观察的instance1 和观察者instance1,而async 的订阅是可观察的instance2 和观察者instance2。所以,当你调用randomizeIt() 时,你调用observer2 instance2 绑定到由async 订阅的可观察的instance2

    让你的 observable “热”:

    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,您都会获得一个新的随机值。每个订阅者的价值都不相同。因为每个订阅者都有一个新实例。

    来自文档:

    将冷和热的 Observable 视为人们可以观看(“订阅”)的电影或表演会有所帮助。

    Cold Observables:电影。
    Hot Observables:现场表演。
    Hot Observables 回放:录制在视频中的现场表演.

    每当您观看电影时,即使所有电影观看者看到的效果都相同,但您的电影放映独立于其他人的放映。另一方面,现场表演被分享给多个观众。如果您迟到参加现场表演,您只会错过其中的一部分。但是,如果它被录制在视频中(在 RxJS 中,这会发生在 BehaviorSubject 或 ReplaySubject 中),您可以观看现场表演的“电影”。 .publish().refCount() 现场表演是艺术家在无人观看时停止播放,并在观众中至少有一个人时重新开始播放的表演。

    【讨论】:

    • 谢谢!我理解 Q1 的答案。但我还不明白Q2。我注意到如果我删除 {{ observable2 | async }},我的observer2订阅将在randomizeIt上触发。需要更多的咖啡
    • @user2073082 完全正确,因为当您删除 {{ observable2 | async }} 时,将只有一个 observable2 实例。换句话说,您只调用了一次this.observable2.subscribe()。因此,您只有该 Observable 的一个实例。
    • @user2073082 检查this plunkerobservable2 将发出一个随机值。因为该 Observable 有两个实例。 {{ observable2 | async }} 上的值与日志中的不同。
    • AAAAAAHHHHHHHHHHHHHHH......我现在明白了!每次我在 observable2 上调用 subscribe 时,它​​都会创建一个新的 observable 并将 this.observer2 设置为该新 observable 的观察者!!!!男孩,术语令人困惑。似乎应该对“observable2”和从 observable2.subscribe 创建的 observable 使用不同的术语...而不是同时调用两个 observable。混乱!
    • @user2073082 很高兴听到这个消息。 AAAAHHH时刻总是最好的:)。而且,你是对的。 observable2 更像是一个可观察的创造者。因此Observable.create(...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2023-03-12
    • 1970-01-01
    • 2018-07-28
    • 2017-03-21
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多