Angular 4: ¿Cuál es la forma correcta de “esperar la operación”?

Me encuentro con un problema simple que tiene una solución hacky de setTimeout(...,0) .

Mirando este código simple:

 @Component({ selector: 'my-app', template: ` 
Span To Detect
`, }) export class App { Items:Array = new Array(); 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" } }

Si hago clic en el botón, la alerta muestra “0”. Entiendo por qué está sucediendo. Es porque Angular no completó su ciclo para poblar realmente el ngFor .

Sin embargo, hacer este truco con setTimeout(..,0) parece un poco raro y prefiero no confiar en él.

Pregunta:

¿Cuál es la forma correcta de “esperar la operación” en Angular? (para que yo vea “10”)

Plnkr

1) Puede obligar a Angular a actualizar el DOM llamando a cdRef.detectChanges

 constructor(private cdRef: ChangeDetectorRef) {} analyzeDom(){ this.cdRef.detectChanges(); alert($("div .mySpan").length) 

Plunker

Como setTimeout es macrotask, por lo tanto, se está ejecutando el siguiente ciclo de resumen. Significa que después de llamar a setTimeout , se verificarán todos los componentes del árbol

cdRef.detectChanges no llama a appRef.tick() . Solo ejecuta el componente de detección de cambios en sí y sus hijos.

2) o puede esperar hasta que Angulat haya actualizado DOM suscribiéndose a zone.onMicrotaskEmpty

 import 'rxjs/add/operator/first'; constructor(private zone: NgZone) {} ... this.zone.onMicrotaskEmpty.first().subscribe(() => this.analyzeDom()); 

Nota: el primer operador puede causar pérdida de memoria. Ver https://github.com/angular/material2/issues/6905

Suscribirse a onMicrotaskEmpty no llama ciclo de detección de cambios

Plunker