Jit*_*hin 16 memory-leaks subscriptions setinterval angular2-observables angular
我需要在一个间隔中刷新组件页面中的数据.此外,我需要在执行某些操作后刷新数据.我在服务中使用Obeservables,以便我可以在响应准备好时订阅.我正在推送对象的订阅,以便我可以清除它ngDestroy
,我认为,我有以下方法来实现相同的目标.
方法1:setInterval
我已经设置了一个间隔ngOnInit
,它将以相等的间隔调用refreshData.将使用clearInterval
in ngOnDestroy
方法清除interval对象.
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();
}
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
Q2:我在这里有同样的问题(Q1).这样,也会将定时器添加到订阅对象,因此实际上订阅对象中的订阅加倍.
Q3:要在动作方法 - doAction()之后刷新数据,将调用refreshData.那会创建另一个计时器链吗?
问题4:没有内存泄漏或者是否存在其他方式,哪种方式更好?
Spa*_*zzy 22
您应该可以毫无问题地执行此操作:
ngOnInit() {
this.refreshData();
this.interval = setInterval(() => {
this.refreshData();
}, 5000);
}
refreshData(){
this.myService.getData()
.subscribe(data => {
this.data = data;
})
);
}
Run Code Online (Sandbox Code Playgroud)
根据这篇文章, 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
}
Run Code Online (Sandbox Code Playgroud)
随着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);
})
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以避免多个订阅,并使数据流可用于任何需要它的组件.
我只是稍微扩展了@SpaceFozzy 的答案,以便它对这里的未来访问者有所帮助。为了刷新数据,我使用了@SpaceFozzy的方式。但是对于订阅,我有一个更好的方法。请看看答案 - /sf/answers/2882401441/。所以我更新了我的服务和组件如下。希望这可以帮助。
我的组件
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();
}
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
我的服务
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;
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
42056 次 |
最近记录: |