2016-03-03 58 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