Angular2 / 4: update data in real time

I need to update the data on the component page in one interval. I also need to update the data after performing some actions. I use Obeservables in the service so that I can subscribe when the answer is ready. I am pushing subscriptions to an object so that I can understand that on ngDestroy , I think I have the following methods to achieve the same.

Method 1: setInterval

I set the interval to ngOnInit , which will call refreshData in equal interval. The interval object will be cleared using the clearInterval method in ngOnDestroy .

 export class MyComponent implements OnInit, OnDestroy { private subscription: Subscription = new Subscription(); data: any; interval: any; ngOnInit() { this.refreshData(); this.interval = setInterval(() => { this.refreshData(); }, 5000); } ngOnDestroy() { this.subscription.unsubscribe(); clearInterval(this.interval); } refreshData(){ this.subscription.add( this.myService.getData() .subscribe(data => { this.data = data; }) ); } doAction(){ this.subscription.add( this.myService.doAction() .subscribe(result => { if(result === true){ this.refreshData(); } }) ); } } 

Q1: Each time the update is called, the subscription will be added to the subscription object, which will increase memory usage and may lead to browser crash if the user opens the page for some time?

Method2: Observable.timer

This method uses a timer that will be created after updating the data.

 export class MyComponent implements OnInit, OnDestroy { private subscription: Subscription = new Subscription(); data: any; ngOnInit() { this.refreshData(); } ngOnDestroy() { this.subscription.unsubscribe(); } refreshData(){ this.subscription.add( this.myService.getData() .subscribe(data => { this.data = data; this.subscribeToData(); }) ); } subscribeToData(){ this.subscription.add( Observable.timer(10000).subscribe(() => this.refreshData()) ); } doAction(){ this.subscription.add( this.myService.doAction() .subscribe(result => { if(result === true){ this.refreshData(); } }) ); } } 

Q2: I have the same question (Q1) here. Thus, timers are also added to the subscription object, so in fact the subscriptions in the subscription object are doubled.

Q3: To update the data after the action method - doAction (), refreshData is called. So will this create another timer chain?

Q4: What is the best way without memory leaks or if there is any other way?

+5
source share
3 answers

You can do it without problems:

 ngOnInit() { this.refreshData(); this.interval = setInterval(() => { this.refreshData(); }, 5000); } refreshData(){ this.myService.getData() .subscribe(data => { this.data = data; }) ); } 

For this post, Angular will take care of cleaning up after itself.

However , if you have a real-time data stream in the application, I would suggest changing your component so that instead of subscribing to every response of your HTTP service request, you instead subscribe once to the new observable data$ property of your service in your component ngOnInit() . Then for the interval (how you do it) call updateData() in your service (or configure the interval inside your service), but do not subscribe. When your service successfully retrieves data, it pushes the following value to the observed property data$ , providing you with a stream of data from your service that you can respond to anywhere in your application.

 ngOnInit() { this.myService.data$.subscribe(data => { // subscribe once to the data stream this.data = data; }) this.refreshData(); this.interval = setInterval(() => { this.refreshData(); }, 5000); } refreshData(){ this.myService.updateData(); // simply signal for the service to update its data stream } 

With myService.data$ being the myService.data$ observable behavior updated in your service, something like this:

 public data$: BehaviorSubject<any> = new BehaviorSubject({}); updateData() { let data = this.http.get('http://www.data.com').map((data)=>{ return data.json(); }).do((data)=>{ this.data$.next(data); }) } 

This way you can avoid multiple subscriptions and make the data stream available to any component that it needs.

+8
source

I just extend @SpaceFozzy a bit so that it is useful for future visitors here. To update the data, I used the @SpaceFozzy method. But for the subscription, I got a better approach. Please take a look at the answer - fooobar.com/questions/26462 / .... Therefore, I updated my service and component as follows. Hope this helps.

My component

 import { Subject } from 'rxjs/Subject'; export class MyComponent implements OnInit, OnDestroy { private unsubscribe: Subject = new Subject(); data: any; interval: any; ngOnInit() { this.refreshData(); if(this.interval){ clearInterval(this.interval); } this.interval = setInterval(() => { this.refreshData(); }, 10000); this.myService.data$.takeUntil(this.unsubscribe) .subscribe(data => { this.data = data; }); } ngOnDestroy() { this.unsubscribe.next(); this.unsubscribe.complete(); } refreshData(){ this.myService.updateData() .takeUntil(this.unsubscribe) .subscribe(); } doAction(){ this.subscription.add( this.myService.doAction() .subscribe(result => { if(result === true){ this.refreshData(); } }) ); } } 

My service

 import { Observable, BehaviorSubject } from 'rxjs'; @Injectable() export class MyService { private dataSubject: BehaviorSubject<YourDataModel[]> = new BehaviorSubject([]); data$: Observable<YourDataModel[]> = this.dataSubject.asObservable(); updateData(): Observable<any> { return this.getData().do((data) => { this.dataSubject.next(data); }); } // My data is an array of model objects getData(): Observable<YourDataModel[]>{ return this.http.get('/path') .map((response: Response) => { let data = response.json() && response.json().your_data_objects; if(data){ return data; } }) } } 
+1
source

Just run this command in the project folder for the linux user:

 sudo sysctl fs.inotify.max_user_watches=524288 sudo sysctl -p --system 
0
source

Source: https://habr.com/ru/post/1269558/


All Articles