Подтвердить что ты не робот

Как устраняются вложенные Angular2 асинхронные каналы?

Я немного запутался в том, как и когда вложенные async-каналы разрешают в шаблонах angular2, и документация не находится в отличном месте прямо сейчас, поэтому я надеюсь, что кто-то из SO может помочь.

У меня очень простое Rxjs Observable, возвращаемое службой, через Observable.of(myArray).delay(2000) - задержка там, чтобы показать, что происходит с синхронизацией.

В моем шаблоне я просто использую async-канал для наблюдаемого, возвращенного выше, в охватывающем теге <p> для управления, когда он отображается, а затем пытается показать возвращаемую длину массива внутри этого тега <p>

<p *ngIf="!(lists | async)">Waiting for lists...</p>
<p *ngIf="lists | async">We have lists! How many? => {{(lists | async)?.length}}</p>

Просмотр Plunker.

Итак, когда вы загружаете это, отображается "ожидание списков", через 2 секунды мы получаем "У нас есть списки!". как ожидается, но затем потребуется еще 2 секунды, чтобы внутренний асинхронный канал разрешил и отобразил разрешенную длину массива.

Как я могу получить длину, чтобы отображаться в то же время, что и все остальное, что зависит от того, что Observable возвращает свои значения? Или это просто не подходит для асинхронных труб, и я должен просто subscribe() в моем компоненте?

4b9b3361

Ответ 1

Асинхронные трубы просто прекрасны. В этом вопросе есть еще одна вещь.

Проверьте исходный код директивы NgIf.

Когда условие истинно, оно ввело вид в контейнер представления.

this._viewContainer.createEmbeddedView(this._templateRef);

Документы для ViewContainerRef # createEmbeddedView

Создает встроенный вид на основе шаблонаRef и вставляет его в этот контейнер с указанным индексом.

В основном он принимает все, что находится внутри NgIf, создает его и помещает в DOM.

Когда условие ложно, оно удаляет все из DOM и очищает все его виды внутри

this._viewContainer.clear();

Документы для ViewContainerRef # clear

Уничтожает все представления в этом контейнере.

Итак, теперь, когда мы знаем, что делает NgIf, почему вы видите это поведение? Простой, и я объясню это шагами.

  • <p *ngIf="!(lists | async)">Waiting for lists...</p>: В этот момент результат lists еще не появился, поэтому он выполняется.

  • <p *ngIf="lists | async": Этот ngIf будет выполнен через две секунды (время задержки, которое вы установили для него). После того, как значение достигнет, директива NgIf будет инстанцировать то, что внутри, и поместить ее в DOM.

  • (lists | async)?.length: этот асинхронный канал выполняется, как только он был установлен, на две секунды позже, чем указано выше.

Итак, ваша временная шкала будет выглядеть так (мне очень жаль, мой плохой график)

*ngIf="lists | async" 
----(2 seconds)-----> 

                     (lists | async)?.length 
                     ------(2 seconds)----->   
                                              print value

Вот почему вы видите эту разницу. *ngIf не работает параллельно с ?.length.

Если вы хотите увидеть его немедленно, вам придется удалить оператор delay или подписаться вручную и установить значение самостоятельно, как показано ниже.

// Template
<p *ngIf="lists">We have lists! How many? => {{lists.length}} some value</p>

// Observable
this._listService.getLists(2000).subscribe(res => this.lists = res);

Это, конечно, повлияет на ваши другие асинхронные каналы. Смотрите plnkr, когда ваш код работает.

Надеюсь, это поможет и немного разъяснит.