2
votes

I have a service which exposes a function that returns Observable. In this service I have some logic which should trigger a next call on the Observable so that subscribed component should get the updated data. During Observer constructor I can call next and everything works great, but how can I access this outside of the constructor?

During service init I do

private currentWheaterData$: Observable<any>;

this.currentWheaterData$ = new Observable(observer => {
    observer.next(/* data */);
}

Then in other methods of the same service I want to be able to execute something like

this.currentWheaterData$.observer.next(/* fresh data */);

There must be a way to emit a new data.

3

3 Answers

2
votes

When you want to create a shared service that holds state, and can be used by components then you should use a BehaviorSubject() so that components will always receive the most recent state.

@Injectable()
export class WeatherService {
   private _weather$ = new BehaviorSubject<WeatherData>(null);

   public function set(data: WeatherData) {
      this._weather$.next(data);
   }

   public function select(): Observable<WeatherData> {
      return this._weather.asObservable();
   }
}

The above will emit a null until the weather data is set. You can alternatively prevent the observable from emitting null and force subscribers to wait until the first data is availible by switching to a new ReplaySubject<WeatherData>(1) instead.

Services can grow in complexity and there are several third-party libraries that can handle state management. Two very popular ones are NgRx and NgXs, but if you're doing something small and want to stay simple. Try my tiny state service that can be used with any front-end framework.

https://github.com/reactgular/stateful

2
votes

In your Weather Service:

public currentWheaterData = new BehaviorSubject<any>(null);

Insert data into Subject - Source Component

constructor(private weatherService:WeatherService){}
this.weatherService.currentWheaterData.next('data');

Destination Component

subscription:Subscription

this.subscription = this.weatherService.currentWheaterData.asObservable().subscribe((data)=>{
console.log(data);
});

Also, unsubscribe when the component destroy

onDestroy(){
this.subscription.unsubscribe();
}
2
votes

Consider using a Subject.

this.currentWeatherData$ = new Subject();

And then you can call at any point:

this.currentWeatherData$.next(/* data */);

in your component you subscribe same as observable:

this.currentWeatherData$.subscribe(/* data */)

https://rxjs-dev.firebaseapp.com/guide/subject