如何修复订阅泄漏Angular Ngrx存储

时间:2019-02-15 14:06:17

标签: angular ngrx ngrx-store

我有一个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 dev工具),而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();

1 个答案:

答案 0 :(得分:0)

在reducer中,当您删除小马时,您是直接在改变状态而不是返回新的不可变状态。尝试应用以下更改:

case PonyRacerActions.DELETE_PONY:
            return {
                ...state,
                races: state.races.filter(race => race != action.payload),
                currentRaces: []
            }