Angular2模板尝试在它之前访问异步数据

时间:2016-02-18 05:56:17

标签: javascript asynchronous angular

我有一个DashboardComponent,它会向用户显示某些常规数据。其中一个数据点就是我们拥有的用户数量。

我还有一个UserService,它有一个名为getUsers()的方法,它返回JSON映射的HTML响应。所以,在DashboardComponent我订阅了这个回复:

this._uService.getUsers()
               .subscribe(
                 users => this.users,
                 error => alert(error)
               )

所以现在我所要做的就是在DOM中显示这个数组的长度,比如

We have {{users.length}} users on board!

(或者在DashboardComponent中创建一个名为companyCount的变量,并将其等同于users数组长度。)

这里的问题是,当我这样做时,它告诉我用户尚未定义。这是可以理解的,因为它是一个可观察的,当它试图访问它时,它不存在。但我对解决方案不太确定。

对我来说,奇怪的是,即使{{users.length}}(或甚至{{users [0]}})出错,我仍然可以使用* ngFor #user用户,并显示全部用户很好地在一个表中,它不会给我一个错误。

我找到了解决办法,尽管这不是我想要的。我从来没有真正得到用户数组,而是这样做:

this._uService.getUsers()
               .subscribe(
                 users => this.userCount = user.length,
                 error => alert(error)
               )

然后在模板中

<div *ngIf="userCount">We have {{userCount}} users on board!!</div>

因此,在定义userCount之前不会显示此div,这意味着订阅数据已可用。

这对我来说看起来不是一个好的解决方案,特别是因为在仪表板上我最终需要显示更复杂的计算,表格等统计数据。

解决这个问题的一般方法是什么?

2 个答案:

答案 0 :(得分:1)

使用猫王或安全导航操作员

{{users?.length}} 

这种方式length仅在user!= null

时进行评估

答案 1 :(得分:0)

组件在内容到达之前尝试呈现。

您无法控制数据何时到达,因为它是异步获取的。相反,使用null object pattern设置默认值(即null对象未定义),因此您需要检查一些内容。

<强>服务

this.users = [];

this._uService.getUsers()
               .subscribe(
                 users => this.users,
                 error => alert(error)
               )
               .startWith(this.users);

注意:startsWith()设置一个空的初始值(即空对象模式),为您的模板提供一些要检查的内容。

<强>组件

this._uService.getUsers().subscribe(users => this.users = users)

注意:提取和存储组件本地长度没有任何好处。最好尽量避免存储中间状态。

<强>模板

<div *ngIf="users.length > 0">We have {{ users.length }} users on board!!</div>

如果您想对用户数组执行更多操作,请使用<template>元素包装该组。

<强>模板2

<template [ngIf]="users.length > 0">
<div>We have {{ users.length }} users on board!!</div>
<div *ngFor="#user of users">
  {{ user.name }}
</div>
</template>

只有template内容才会显示在ContentView中。如果users.length不大于0,则不会进行其他检查,并且template内容不会显示在ContentView中。

如果您正在使用通过observable异步加载的复杂对象,我发现在模板组周围添加template包装器是最干净的方法。