Angular 更改检测仅在连续的 Ngrx 存储更新时触发一次

Angular change detection only triggering once on consecutive Ngrx-store updates

在以下情况下,Angular 更改检测未按我预期的方式触发。我正在使用 ngrx-store 来保存我的应用程序状态。

  1. 最初,我有状态 S1。
  2. 我触发了一个动作A1。侦听 A1 的减速器将状态更新为 S2。效果触发动作 A2.
  3. 侦听 A2 的减速器将状态更新回 S1。

在上述情况下,有两个状态更新(S1 -> S2 -> S1)。但是,在这一系列操作结束时,我的组件 OnChange 只触发一次(S1 -> S1)。我正在使用带有异步管道的标准 Observable 和带有 @Input 的子组件。

@Component({
    selector: 'app-parent-component',
    template: `<app-time-entry [timeEntry]="timeEntry$ | async"></app-time-entry>`
})
export class ParentComponent {
    timeEntry$: Observable<TimeEntryRow>;

    constructor(private store: Store<AppState>) {
        this.timeEntry$ = this.store.select(state => state.time.timeEntry);
    }
}

@Component({
    selector: 'app-time-entry',
    template: `{{timeEntry.hours}}`
})
export class TimeEntryComponent {
    @Input() timeEntry: TimeEntry;
}

为什么在这种情况下变化检测只发生一次?我已验证我的状态在每个操作之间正确更新,那么为什么绑定只更新一次?我希望异步管道将更改后的状态传递两次,从而也触发子组件 OnChange 两次。

更新

正如下面 Kevin 所建议的,在效果中添加延迟会导致两个 OnChanges 按预期触发。这表明 Angular "tick" 是在两个状态更新完成后发生的。

这可能是正常的。你的状态在同一个 'tick' 期间改变了两次(即:你调度动作 A1 改变了两次状态,一次直接来自处理你的动作的减速器,第二次来自调度第二个动作的效果)。

但是变更检测是 运行 一次。所以你只能看到最后的变化。我想如果您的效果是稍后分派操作(可能通过使用延迟运算符),您会看到 OnChanges 被调用两次。我很惊讶你看到 S2->S1 而不是 S1->S1 发生了变化(它们具有相同的内容,但由于状态是不可变的,所以它们是不同的对象),所以它可能不是正在发生的事情。

如果不查看所有代码,很难判断这是不是正在发生的事情。你的效果是什么样的?它是立即调度一个动作,还是做某种 AJAX 请求,并在获得结果时调度动作?