2016-03-03 46 views
10

對於如何以及何時在angular2模板中嵌套異步管道解決問題,以及文檔現在不在很好的位置,我很困惑,所以我希望SO上的某個人能夠提供幫助。嵌套的Angular2異步管道如何解決?

我有一個非常簡單的Rxjs Observable從服務返回,通過Observable.of(myArray).delay(2000) - 延遲是有幫助顯示正在進行的時間。

在我的模板,我只是用在觀察到在封閉<p>標籤以上恢復控制的異步管道時,將顯示它,然後試圖表明<p>標籤內返回數組長度:

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

View the Plunker.

所以,當你加載這個了,「等待名單」顯示,2秒後,我們得到了「我們列出了!」如預期的那樣,但內部異步管道需要花費另外2秒才能解析並顯示已解析的數組長度。

如何根據Observable返回的值同時顯示與其他所有內容相同的顯示長度?或者這對於異步管道來說不是一個好用例,我應該在組件中使用subscribe()而不是?

回答

10

異步管道很好。還有一件事涉及這個問題。

檢查NgIf指令源代碼。

當條件爲真時,它將視圖嵌入到視圖容器中。

this._viewContainer.createEmbeddedView(this._templateRef); 

文檔爲ViewContainerRef#createEmbeddedView

實例化基於所述templateRef嵌入式視圖並將其插入到指定的索引在該容器中。

基本上它需要它在NgIf中的任何東西,實例化它並將其放入DOM中。

當條件爲假它從DOM中刪除一切,將其清除

this._viewContainer.clear(); 

文檔內部的所有意見的ViewContainerRef#clear

銷燬在這個容器中的所有意見。

所以,現在我們知道NgIf做了什麼,爲什麼你會看到這種行爲?很簡單,我會解釋它在步驟

  1. <p *ngIf="!(lists | async)">Waiting for lists...</p>:此時lists結果還沒有到來,所以這是執行。

  2. <p *ngIf="lists | async":該ngIf將在兩秒內執行(您設置的延遲時間)。一旦這個值到達,NgIf指令就會實例化它裏面的內容並把它放到DOM中。

  3. (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

我希望這有助於澄清一點。

+0

謝謝 - 有道理。在我的observable上使用'delay()'可以讓我更深入地瞭解'* ngIf'如何工作:) – chucknelson

+6

也許有必要提一下,源觀察值不以任何方式共享*好。在最初的場景中,'lists' observable被訂閱兩次(一次用於'ngIf',然後用於'length'),並且在每個訂閱上流重新開始,包括延遲。如果'lists'被共享,重播或者變熱,第二次訂閱會馬上找到最終的數組值,而不會有新的延遲。 – superjos