Angular 如何修复ngrx存储中的订阅泄漏
我有一个ponyracer应用程序,它实现了ngrx商店。非常基本的功能:开始比赛,添加小马,删除小马,分数表。当我移除或添加小马时,问题就来了——基本上,这个功能是指创建或销毁小马组件。因此,由于某种原因,任何添加的小马都会存储在某个地方,即使在销毁了一个组件之后,应用程序仍然可以访问所有添加和删除的小马,并对它们进行迭代,例如,当我只需要查看现有小马的分数时,但会显示所有(甚至以前删除的)小马 我使用store.select.pipe(…).subscribe(),不需要使用onDestroy和unsubscribe() 组件Angular 如何修复ngrx存储中的订阅泄漏,angular,ngrx,ngrx-store,Angular,Ngrx,Ngrx Store,我有一个ponyracer应用程序,它实现了ngrx商店。非常基本的功能:开始比赛,添加小马,删除小马,分数表。当我移除或添加小马时,问题就来了——基本上,这个功能是指创建或销毁小马组件。因此,由于某种原因,任何添加的小马都会存储在某个地方,即使在销毁了一个组件之后,应用程序仍然可以访问所有添加和删除的小马,并对它们进行迭代,例如,当我只需要查看现有小马的分数时,但会显示所有(甚至以前删除的)小马 我使用store.select.pipe(…).subscribe(),不需要使用onDestro
export class RacesComponent implements OnInit {
racesState: Observable<fromPonyRacer.State>;
constructor(private store: Store<fromApp.AppState>) { }
ngOnInit() {
this.racesState = this.store.select("raceList");
this.racesState.subscribe()
}
}
export class RaceComponent implements OnInit {
@Input() race: RaceModel;
@Input() index: number;
racesState: Observable<fromPonyRacer.State>;
constructor(private store: Store<fromApp.AppState>) { }
ngOnInit() {
this.racesState = this.store.select("raceList");
this.racesState.pipe(
tap(races => {
if(races.raceStatus) this.movePony();
})
)
.subscribe()
}
}
但是这个动作也会被分派给移除的小马,它们也会到达store.currentRaces,并显示在分数表中。我不知道这些被移除的小马是从哪里来的。因为state.races总是真实和正确的(根据redux开发工具),races.component使用state.races为每匹小马呈现视图,并且总是正确和新鲜的
movePony() {
some code for moving a pony
if(ponyReachedFinish) {
this.store.dispatch(new PonyRacerActions.StopRace({name: this.race.name, place, points})
}
}
如果需要更多详细信息,您可以在此处找到完整的代码:
更新:问题已解决。正如我最初设想的那样,问题是由于订阅泄漏而发生的。我应用了OnDestroy,在这个方法中应用了一行代码
this.subscription.unsubscripte() 在reducer中,删除小马时,直接改变状态,而不是返回新的不可变状态。尝试应用以下更改:
case PonyRacerActions.DELETE_PONY:
return {
...state,
races: state.races.filter(race => race != action.payload),
currentRaces: []
}
在reducer中,当删除小马时,直接改变状态,而不是返回新的不可变状态。尝试应用以下更改:
case PonyRacerActions.DELETE_PONY:
return {
...state,
races: state.races.filter(race => race != action.payload),
currentRaces: []
}
如果在热观测上使用
subscribe
,为什么不需要使用onDestroy和unsubscribe()
?这应该是强制性的。我是第二个@trichetriche。如果您要订阅存储区中的可观察对象,则需要使用异步
管道进行订阅,或者在组件中显式调用.unsubscribe()
。@Trichetrich流是热的这一事实与此问题并不相关,而流是无限的。是的,尽管订阅Observable是一种糟糕的做法,但它肯定不是bug的原因。在移除小马的地方张贴减速器的代码。@Jota.Toledo无论异步管道订阅可观察对象,还是在组件中执行,都不会更改发出的值。很明显,他的错误在他的还原器中的某个地方,而还原器实际上决定了他的应用程序的状态。如果你在热观测上使用subscribe
,为什么没有必要使用onDestroy和unsubscribe()
?这应该是强制性的。我是第二个@trichetriche。如果您要订阅存储区中的可观察对象,则需要使用异步
管道进行订阅,或者在组件中显式调用.unsubscribe()
。@Trichetrich流是热的这一事实与此问题并不相关,而流是无限的。是的,尽管订阅Observable是一种糟糕的做法,但它肯定不是bug的原因。在移除小马的地方张贴减速器的代码。@Jota.Toledo无论异步管道订阅可观察对象,还是在组件中执行,都不会更改发出的值。很明显,他的错误在他的还原程序中的某个地方,而还原程序实际上决定了他的应用程序的状态。尝试了这种方法更新还原程序,但仍然面临相同的问题。删除小马->开始比赛->仍然可以在分数表中看到删除的小马尝试了这种方式更新减速器,但仍然面临相同的问题。删除小马->开始比赛->仍然可以在分数表中看到删除的小马
movePony() {
some code for moving a pony
if(ponyReachedFinish) {
this.store.dispatch(new PonyRacerActions.StopRace({name: this.race.name, place, points})
}
}
case PonyRacerActions.DELETE_PONY:
return {
...state,
races: state.races.filter(race => race != action.payload),
currentRaces: []
}