Angular 如何防止从这个角度泄漏6 rxjs 6
我在authService.ts中有以下函数 它可以工作,但是订阅泄露了。它存在于一项服务中,几乎每个组件都在整个应用程序中使用Angular 如何防止从这个角度泄漏6 rxjs 6,angular,Angular,我在authService.ts中有以下函数 它可以工作,但是订阅泄露了。它存在于一项服务中,几乎每个组件都在整个应用程序中使用 mouseEvents: Subscription; timer: Subscription; constructor() { if(user){ this.updateOnIdle(user.uid); } } private updateOnIdle(userId) { this.mo
mouseEvents: Subscription;
timer: Subscription;
constructor() {
if(user){
this.updateOnIdle(user.uid);
}
}
private updateOnIdle(userId) {
this.mouseEvents = fromEvent(document, 'mousemove')
.pipe(
throttleTime(2000)
)
.subscribe(() => {
firebase.database().ref('/status/' + userId).set({
status: 'online',
last_changed: firebase.database.ServerValue.TIMESTAMP
});
this.resetTimer(userId)
});
}
/// Reset the timer
private resetTimer(userId) {
if (this.timer) {this.timer.unsubscribe()}
this.timer = timer(5000)
.map(() => {
firebase.database().ref('/status/' + userId).set({
status: 'away',
last_changed: firebase.database.ServerValue.TIMESTAMP
});
}).subscribe();
}
我如何解决这个问题?编写函数的更好方法是什么?解决泄漏问题的一个方法是不要在
ts
中使用订阅,而是返回可观察值,让angular的async
管道为您管理订阅
mouseEvents$: Observable<any>;
timer$: Observable<any>;
constructor() {
if(user){
this.updateOnIdle(user.uid);
}
}
private updateOnIdle(userId) {
this.timer$ = fromEvent(document, 'mousemove')
.pipe(
throttleTime(2000),
switchMap(() => firebase.database().ref(`/status/${userId}`).set({status: 'online', last_changes: firebase.database.ServerValue.TIMESTAMP}),
map(your reset timer logic here)
);
this.resetTimer(userId);
});
}
mouseEvents$:可观察;
计时器$:可观察;
构造函数(){
如果(用户){
this.updateOnIdle(user.uid);
}
}
私有updateOnIdle(用户ID){
this.timer$=fromEvent(文档“mousemove”)
.烟斗(
节流时间(2000年),
switchMap(()=>firebase.database().ref(`/status/${userId}').set({status:'online',last_changes:firebase.database.ServerValue.TIMESTAMP}),
映射(此处为重置计时器逻辑)
);
这个.resetTimer(userId);
});
}
然后在html中使用它
<div class="myTimer" [time]="timer$ | async"></div>
从可观察对象取消订阅有不同的方式,您可以调用取消订阅方法,也可以使用自动取消订阅的运算符之一:
- 第一:将在第一次火灾后完成并取消订阅
- take:将在n次激发后完成并取消订阅
- takeUntil:当通过的可观察到的事件发生时,将完成并取消订阅
- takeWhile:将在条件不再为真时完成并取消订阅
您可以为您的案例选择合适的操作员。在回答您后面的问题后,我刚刚看到了这个问题。我现在可以看到更大的图景,以及为什么在另一个问题中没有
subscribe()
调用
本质上,我认为“泄漏”是指在使用该服务的组件被销毁后,鼠标事件继续触发
如果是这样,那么处理它的方法可能是统计服务内部的引用,并在最后一个停止时取消订阅()。大概
@Injectable()
导出类MyService{
mouseEvents:订阅;
定时器:订阅;
参考值=0;
构造函数(){
}
公共启动(){
如果(!参考){
this.updateOnIdle(user.uid);
}
参考文献+=1;
}
公众站{
参考文献-=1;
如果(!参考){
mouseEvents.unsubscribe();
timer.unsubscribe();
}
}
私有updateOnIdle(用户ID){
...
}
在组件中
@Component()
导出类MyComponent实现OnInit、OnDestroy{
建造师(
私有myService:myService
) {}
恩戈尼尼特(){
myService.start();
}
恩贡德斯特罗(){
myService.stop();
}
事实上,我在html中不需要它。只是为了更新数据库。如果你需要更新数据库,你可以在数据库更新后取消订阅。谢谢。但是在你的答案中我将把上面的unsubscribe()方法放在哪里呢?我正在与RXJS作斗争。你只需在管道()之后加上。unsubscribe()