我确定问题是关于异步,但我找不到解决方案。我创建了一个获取JSON数据数组的服务。在我的组件中,我想在加载页面时显示此数据。 加载页面时我没有获得任何数据,但是我创建了一个按钮,并在其onclick事件上添加了相同的功能。我在点击事件上获得了数据。我究竟做错了什么?
我的组件
import { Component } from '@angular/core';
import {PostService} from './post.service';
@Component({
selector: 'app-root',
template: `
{{test}}
<ul>
<li *ngFor="let item of jsonArray">
{{item.title}} a
</li>
</ul>
<button on-click="onClick()">button</button>
`
})
export class AppComponent {
test;
jsonArray : any[];
constructor(private _postService : PostService){
}
onClick(){
this.jsonArray = this._postService.getPosts();
this.test = "clicked";
}
ngOnInit(){
this.jsonArray = this._postService.getPosts();
this.test = "init";
}
}
和我的服务类
import {Http} from '@angular/http'
import 'rxjs/add/operator/map';
import {Injectable} from '@angular/core';
@Injectable()
export class PostService {
private _url = "https://jsonplaceholder.typicode.com/posts";
jsonArray: any[];
getPosts():any[]{
//return this._http.get(this._url).map(res =>res.json());
this._http.get(this._url).subscribe(response => {
this.jsonArray = response.json();
console.log(response.json());
console.log("jsonArray",this.jsonArray);
});
return this.jsonArray;
}
createPost(post){
return this._http.post(this._url,JSON.stringify(post)).map(res =>res.json());
}
constructor(private _http:Http ){
}
}
答案 0 :(得分:2)
您的服务有两个问题:
return
在回调之外,因此将返回初始空数组subscribe
返回数据。我建议您阅读异步性:How do I return the response from an asynchronous call?
此How do I return the response from an Observable/http/async call in angular2?在更多Angular场景中解释了这种行为。
同时阅读 official tuto of http 。
话虽如此,很快就说 - 你需要map
在服务中,subscribe
在组件中。
关于你的问题:
我在页面加载时没有获得任何数据,但是我创建了一个按钮,并在其onclick事件上添加了相同的功能。我在点击事件上获得了数据。
让我们深入了解您的服务方法,看看发生了什么:
getPosts():any[]{
this._http.get(this._url).subscribe(response => {
// hey, I'm doing this request now, but I don't know how long it will take
this.jsonArray = response.json();
console.log(response.json());
console.log("jsonArray",this.jsonArray);
});
/* okay, so I fired the above request, I won't wait until it is complete,
I'll just execute the below while I am waiting!*/
return this.jsonArray;
}
因此,当您在OnInit
上触发请求时,它会执行http请求,并且在执行时它会在http请求执行完之前返回this.jsonArray
。
所以现在当你点击按钮时,它会重新启动http请求,在它再次完成之前,会再次返回this.jsonArray
。但是,嘿,现在我们实际上已经从之前的请求获得了值,所以这就是为什么你得到的数据就好了!
正如前面提到的,无论如何你都无法从subscribe返回数据,即使它是在回调中也是如此:
getPosts():any[]{
return this._http.get(this._url).subscribe(response => {
....
return this.jsonArray; // WON'T WORK!
});
}
所以你可以做的是从map
返回数据,所以:
<强>服务强>
getPosts():any[]{
this._http.get(this._url)
.map(res => res.json())
});
}
<强>组件:强>
ngOnInit(){
this._postService.getPosts()
.subscribe(data => this.jsonArray = data)
}
我真的建议您仔细阅读所提供的链接并仔细阅读:)