我需要在一个间隔中刷新组件页面中的数据。此外,我需要在执行某些操作后刷新数据。我在服务中使用Obeservables,以便我可以在响应准备好时订阅。我正在推送对象的订阅,以便我可以在ngDestroy
上清除它,我认为,我有以下方法来实现相同的目标。
方法1:setInterval
我在ngOnInit
上设置了一个间隔,它将以相等的间隔调用refreshData。将使用clearInterval
方法中的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:在每次刷新调用时,订阅都会添加到subscription
对象中,这会增加内存使用量,如果用户保持页面打开一段时间,浏览器可能会崩溃吗?
方法2:Observable.timer
此方法使用将在刷新数据后创建的计时器。
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:我在这里有同样的问题(Q1)。这样,也会将定时器添加到订阅对象中,因此实际上订阅对象中的订阅加倍。
问题3:要在动作方法 - doAction()之后刷新数据,将调用refreshData。这样会创建另一个计时器链吗?
问题4:没有内存泄漏或者是否存在其他方式,哪种方式更好?
答案 0 :(得分:19)
您应该可以毫无问题地执行此操作:
ngOnInit() {
this.refreshData();
this.interval = setInterval(() => {
this.refreshData();
}, 5000);
}
refreshData(){
this.myService.getData()
.subscribe(data => {
this.data = data;
})
);
}
根据this post Angular将自行清理。
然而,如果您要在应用中使用实时数据流,我建议更改您的组件,以便不是订阅服务的http请求的每个响应,而是订阅一次到您的组件的data$
中的服务的新的可观察ngOnInit()
属性。然后,按时间间隔(正如您所做的那样)在您的服务上调用updateData()
(或在服务中设置间隔),但不要订阅。当您的服务成功提取数据时,它会将下一个值推送到其可观察的data$
属性,从而为您提供服务中的数据流,您可以对应用中的任何位置做出反应。
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
}
myService.data$
在您的服务中更新了可观察的BehaviourSubject,如下所示:
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);
})
}
这样,您可以避免多个订阅,并使数据流可用于任何需要它的组件。
答案 1 :(得分:3)
我只是稍微扩展@ SpaceFozzy的答案,以便它对今后的访问者有所帮助。为了刷新数据,我使用了@SpaceFozzy的方式。但对于订阅,我有一个更好的方法。请看一下答案 - https://stackoverflow.com/a/41177163。所以我更新了我的服务和组件,如下所示。希望这会有所帮助。
我的组件
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();
}
})
);
}
}
我的服务
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;
}
})
}
}
答案 2 :(得分:0)
请不要忘记在ngDestroy上清除Interval。
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
clearInterval(this.interval);
}
答案 3 :(得分:-13)
只需在linux用户的项目文件夹中运行此命令:
sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl -p --system