【发布时间】:2019-03-21 23:03:45
【问题描述】:
我有一个 ponyracer 应用程序,它实现了 ngrx 商店。非常基本的功能:开始比赛,添加小马,删除小马,分数表。当我删除或添加小马时,问题就出现了——基本上这个功能是指创建或销毁小马组件。因此,任何添加的 Pony 都出于某种原因存储在某处,即使在销毁组件之后 - 应用程序仍然可以访问所有添加和删除的小马,并迭代它们,例如当我只需要查看现有小马的分数时 - 但所有(甚至以前已移除)显示小马
我用的是store.select.pipe(...).subscribe(),不用onDestroy和unsubscribe()
races.component.ts
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()
}
}
races.component.html
<pr-race *ngFor="let race of (racesState | async).races; let i = index"
[race]="race" [index]="i">
</pr-race>
race.component.ts
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()
}
}
race.component.html
<div class="race">
<img class="pony-img" [src]="race.src">
</div>
当小马完成时,将调度动作并将小马添加到名为 currentRaces 的存储属性中,因此存储跟踪哪个小马先完成,第二个完成,依此类推。
const initialState: State = {
races: [
new RaceModel(some data),
new RaceModel(some another data),
new RaceModel(some more data)
],
raceStatus: false,
raceCount: 0,
isNewrace: false,
poniesAreAboutToFinish: null,
currentRaces: []
}
但是这个动作也会被移除的小马调度,它们也会到达 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})
}
}
如果需要更多详细信息,您可以在此处找到完整代码:https://github.com/joistick1/pr2
更新:问题已解决。正如我最初假设的那样,问题是由于订阅泄漏而发生的。我应用了 OnDestroy 并在此方法中应用了一行代码 this.subscription.unsubscribe();
【问题讨论】:
-
如果你在 hot observables 上使用
subscribe,为什么是there is no need to use onDestroy and unsubscribe()?这应该是强制性的。 -
我第二个@trichetriche。如果您要从商店订阅 observable,您需要使用
async管道进行订阅,或者在组件中显式调用.unsubscribe()。 -
@trichetriche 流是 hot 的事实与问题并不真正相关,而流是 infinite 是它的原因。跨度>
-
是的,尽管订阅 Observable 是一种不好的做法,但它绝对不是错误的原因。将你的 reducer 代码贴在你移除小马的地方。
-
@Jota.Toledo 无论是异步管道订阅 Observable,还是您在组件中订阅都不会改变发出的值。很明显,他的错误出在他的 reducer 中,这实际上决定了他的应用程序的状态。
标签: angular ngrx ngrx-store