Смена обнаружения не работает должным образом в компоненте ng2 после навигации через угловое устройство ui-router

В приложении, использующем ng-upgrade, чтобы использовать некоторые новые компоненты ng2 (V2.2.4) внутри большого приложения ng1 (V1.5.9) (с использованием ui-router), в настоящее время я вижу очень странную проблему обнаружения изменений. Насколько я могу судить, это было внесено в некоторое обновление ng2, но, к сожалению, я не могу легко проверить, что в настоящее время.

Я сократил его до минимального примера, теперь, когда у меня просто есть этот компонент:

@Component({
    selector:'my-ng2-demo',
    template: '<div>{{status}}</div>'
})
export class MyNg2Demo implements OnDestroy {
    public status:boolean = true;
    private interval:any;

    constructor() {
        this.interval = setInterval(() => {
            this.status = !this.status;
            console.log('status: ' + this.status);
        }, 2000);
    }

    ngOnDestroy():void {
        clearInterval(this.interval);
    }

}

Этот компонент обновлен в адаптере обновления и зарегистрирован как компонент входа в модуле.

Компонент используется в шаблоне контроллера ng1 следующим образом:

<my-ng2-demo></my-ng2-demo>

Когда я открываю браузер и перехожу непосредственно на эту страницу (маршрут контроллера ng1), все работает так, как ожидалось: ui показывает, что true/false чередуются каждые 2 секунды.

Однако: когда я перемещаюсь, а затем возвращаюсь на страницу (посещая несколько разных маршрутов), то внезапное изменение обнаружения, похоже, не работает. Отображаемое значение чередуется только примерно каждые 5-6 секунд, кажется довольно случайным, хотя в консоли я все еще вижу ожидаемые значения.

Когда я меняю конструктор компонента на это:

constructor(private zone: NgZone) {
    this.interval = setInterval(() => {
        zone.run(() => {
            this.status = !this.status;
            console.log('status: ' + this.status);
        });
    }, 2000);
}

Он снова работает снова.

Очевидно, это не выполнимое решение, так как поведение, которое я вижу в реальном приложении, намного сложнее (мне нужно было бы добавить zone.run в десятки мест, возможно, это было бы не ремонтопригодным).

Я отлаживал это часами и не понимаю, что происходит. В профилировщике JavaScript JavaScript я в основном вижу, что страница простаивает почти все время в те 5-6 секунд, где ничего не происходит.

profiler Это не скриншот из этого демонстрационного компонента (но он в основном выглядит одинаково), но из профилирования вкладки-компонента, который я изначально тестировал (переключение табуляции заняло столько же времени, что между видимыми действиями не было).

обновление:

После немного большего количества экспериментов то, что я нахожу довольно удивительным, также заключается в том, что вместо того, чтобы поместить код изменения статуса в вызов zone.run, я добавляю вызов ApplicationRef.tick()  (как упоминается здесь, например: qaru.site/info/28948/...), он также НЕ работает вообще. Я не понимаю, почему принудительное обнаружение изменений приложения ничего не делает, но вызов зоны работает как-то.

Пример кода с тиковым вызовом, который не работает:

constructor(private applicationRef:ApplicationRef) {
    this.interval = setInterval(() => {
        this.status = !this.status;
        console.log('status: ' + this.status);
        applicationRef.tick();
    }, 2000);
}

Ответы

Ответ 1

В версии Angular есть ошибка. Обнаружение изменений не работает должным образом в ng-обновленных приложениях.

Подробнее см. https://github.com/angular/angular/issues/12318.

Если вы обновляете до 2.4.4, это должно решить проблему.