Angular 4 - Каков правильный способ "ждать работы"?

Я столкнулся с простой проблемой, которая имеет хакерское решение setTimeout(...,0).

Посмотрите на этот простой код:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input value='Fill Data' type='button' (click)='fill()'/>
      <span *ngFor="let o of Items" class='mySpan'>Span To Detect<br></span>
    </div>
  `,
})
export class App {
  Items:Array<number> = new Array<number>();

  fill()
  {
   this.Items = [1,2,3,4,5,6,7,8,9,10]
   this.analyzeDom(); //this has to run here
  }

  analyzeDom()
   {
      alert($("div .mySpan").length) // "0"

     //BUT if I set this hacky trick , it works
     // setTimeout(function (){  alert($("div .mySpan").length)},0) // "10"
   }
}

Если я нажму кнопку, предупреждение покажет "0". Я понимаю, почему это происходит. Это потому, что Angular не завершил свой цикл, чтобы фактически заполнить ngFor.

Однако - этот трюк с setTimeout(..,0) кажется немного взломанным для меня, и я предпочитаю не доверять ему.

Вопрос:

Каков правильный способ "ждать операции" в Angular? (так что я увижу "10" )?

Plnkr

Ответ 1

1) Вы можете заставить Angular обновить DOM, вызвав cdRef.detectChanges

  конструктор (private cdRef: ChangeDetectorRef) {}

analyzeDom() { this.cdRef.detectChanges(); alert ($ ( "div.mySpan" ). length)
Код>

Plunker

Поскольку setTimeout является макрозадачей, поэтому он запускает следующий цикл дайджеста. Это означает, что после вызова setTimeout будет проверено все дерево компонентов

cdRef.detectChanges не вызывает appRef.tick(). Он выполняет только компонент обнаружения изменений и его дочерние элементы.

2), или вы можете подождать, пока Angulat не обновит DOM, подписавшись на zone.onMicrotaskEmpty

  import 'rxjs/add/operator/first';

конструктор (частная зона: NgZone) {}
...
this.zone.onMicrotaskEmpty.first(). subscribe (() = > this.analyzeDom());
Код>

Примечание: первый оператор может вызвать утечку памяти. См. https://github.com/angular/material2/issues/6905

Подписывание onMicrotaskEmpty не вызывает цикл обнаружения изменений

Plunker