Angular 2中带有Observable的http不能使用数据
Posted
技术标签:
【中文标题】Angular 2中带有Observable的http不能使用数据【英文标题】:http with Observable in Angular 2 cant use data 【发布时间】:2017-06-17 03:10:42 【问题描述】:我是 angular 2 和 observables 的新手,但我想试一试。所以我已经安装了 angular-cli 并做了一个简单的测试项目。
我想要做的只是读取一个 json 文件并处理组件内部的数据(最初的目的是提供服务,但我想从低端开始)。
所以我在 assets/json 文件夹 (testjson.json) 中创建了一个 json 文件:
"teststring": "test works"
然后我从我的 content.component.ts 文件中导入了来自 angular 的 http 和 rxjs 地图内容:
import Component, OnInit from '@angular/core';
import Http from '@angular/http';
import 'rxjs/add/operator/map';
@Component(
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css']
)
export class ContentComponent implements OnInit
title: string = "Default";
data;
constructor(private http:Http)
http.get('assets/json/testjson.json').map(res => res.json()).subscribe(data => this.data = data; this.title = data.teststring; console.log(this.data););
ngOnInit()
到目前为止一切顺利,应用程序打印出以下内容:
app works!
test works [object Object]
但我想在整个组件中使用这些数据,而不仅仅是在构造函数中。但是如果我尝试在构造函数之外(在 ngOnInit 函数内)控制台记录“this.data”,它会在控制台中打印 undefined。
我知道,它一定与异步加载有关,但不幸的是我不知道如何告诉应用程序等到 this.data 被填充。
我希望你能帮助我。当然,将来我想要一种服务,它可以做这种事情,并且不止一个组件应该从中获取数据。
提前致谢!
【问题讨论】:
首先将你的异步代码从构造函数移动到 ngOnInit()。承诺解决后您的数据可用 【参考方案1】: 您应该将初始化代码移到初始化方法中。 回调完成后,您的数据将可用。在您的模板中,一旦有数据,您就可以使用*ngIf
在块内执行代码。只要*ngIf
没有评估为真,内部代码就不会运行。
运行console.log(data)
的唯一方法是从回调内部或从回调中调用,因为您必须等到数据加载完毕。
content.component.html
<div *ngIf="data">
<span>data.teststring</span>
</div>
content.component.ts
export class ContentComponent implements OnInit
title: string = "Default";
data: any = null;
constructor(private http:Http)
ngOnInit()
this.http.get('assets/json/testjson.json')
.map(res => res.json())
.subscribe(data =>
this.data = data;
this.title = data.teststring;
console.log(this.data);
);
编辑
回应下面的评论如果您抽象出对服务的 http 调用,您可以看到完全相同的逻辑仍然适用。您仍在使用数据承诺的概念,并且一旦完成,您就可以订阅该承诺。这里唯一的区别是 http 调用被抽象为不同的类。
content.component.ts
export class ContentComponent implements OnInit
title: string = "Default";
data: any = null;
// inject service
constructor(private contentService:ContentService)
ngOnInit()
this.contentService.getData()
.subscribe(data =>
this.data = data;
this.title = data.teststring;
console.log(this.data);
);
服务
export class ContentService
constructor(private http:Http)
getData(): IObservable<teststring:string> // where string can be some defined type
return http.get('assets/json/testjson.json')
.map(res => res.json() as teststring:string);
【讨论】:
好的,谢谢,但是 console.log 只是为了快速测试数据是否存在。想象一下我有一个服务,持有 this.data,我想从一个组件调用服务的 getter 来获取该数据并打印出测试字符串。只要异步请求正在运行,getter 就无法传递正确的数据。因此,如果我在组件内部调用 getter,则服务将提供未定义的服务。如何等待服务填充 this.data? @sonnenpriester - 与您现在所做的完全相同。您从您的服务中返回一个 IObservable,它具有数据的承诺,并从您的组件中订阅它。上面的代码和添加服务的唯一区别是抽象了http
对服务的调用。
@sonnenpriester - 我添加了另一个带有服务的示例。正如您所看到的,这个概念没有改变,您使用做某事的承诺,然后订阅该承诺以在承诺完成时执行某事。
这是否意味着我们对从服务获取数据的每个组件都有一个请求?我的意图是服务发出一个请求并将数据存储在 this.data 中,所有组件只需调用一个 getter 从服务获取存储在 this.data 中的数据。
@sonnenpriester - 您可以将数据结果作为变量缓存在服务中。然后组件检查服务中是否存在数据,如果尚未初始化,则以与上面编写代码相同的方式调用方法。以上是关于Angular 2中带有Observable的http不能使用数据的主要内容,如果未能解决你的问题,请参考以下文章
在 Angular 2 中对 observable 进行单元测试
Angular 2 - 直接从 Observable 返回数据
Angular 2 - 路由 - CanActivate 与 Observable 一起工作