Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
737 views
in Technique[技术] by (71.8m points)

javascript - Observer subscribe not firing on first load to Component

I have a store which exposes an asObservable. A view subscribes to this and displays the data. It was working on first load since I've changed it to a Singleton service, when I first go to the page no data is displayed and no subscribe event triggered. After I perform some operation on the data which causes the subject.next to be called it updates and the view updates and everything is great.

I've ensured this is not a race condition problem and that the data is in the store at the time the page's constructor is called.

Sequence of events is as follows (confirmed during debugging):

  1. Data is loaded from server
  2. subject.next() is called with correct data
  3. component constructor is called which subscribes to observer

No subscribe event fires and no data populates, even though it exists in the store. If I then perform some kind of crud operation on the list everything cascades through as expected, next() is called, and a subscribe event occurs.

How can I get the page to read data on page load?

data.store

protected _subject$: Subject<Array<any>>;
this._subject$.next(newData);  // confirmed via console this happens with good data

get contacts$(): Observable<any> {
  return this._subject$.asObservable();
}

component - I've tried both putting the below block in the constructor and in ngAfterViewInit, same result

// this happens after the above data is already set
this.contacts$.subscribe(data => {
    // this block does not execute on page load
  });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Sequence of events is as follows (confirmed during debugging):

  1. Data is loaded from server
  2. subject.next() is called with correct data
  3. component constructor is called which subscribes to observer

It's because the vanilla Subject doesn't buffer anything. When a message is emitted, if there is no one subscribed at that exact time, then the message is gone forever and no one will receive it.

If you want to keep the last message buffered (for all subscribers), then you can use the BehaviorSubject or the ReplaySubject

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ReplaySubject } from 'rxjs/ReplaySubject';

sub1 = new BahaviorSubject<any>(null);
sub2 = new ReplaySubject<any>(1);

Semantically, the BehaviorSubject represents a value that changes over time, and you initialize it with the initial value. It will keep the last item always buffered until the next item pushes it out.

The Semantics of the ReplaySubject is to buffer the number of items emitted, up to the buffer size, and send them all to subscribers when subscribed to. We can initialize the ReplaySubject with a buffer size. A buffer size of 1, will make it behave just like a BehaviorSubject (but we don't need to initialize it with a value).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...