Angular 2 中的嵌套 Observable
Nested Observable in Angular 2
我正在尝试 Angular 2 的 http GET 来检索 HackerNews 上的热门文章列表,之后我将在嵌套的可观察对象中检索它们各自的详细信息。
当我尝试循环显示 HTML 中的数据时遇到此错误。
Cannot find a differ supporting object '[object Object]'
此外,我猜应该有更好的方法来做到这一点,任何指示?
getTopPost() {
this.http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.subscribe(
data => {
data.map(function(postId){
let storyUrl = "https://hacker-news.firebaseio.com/v0/item/"+ postId +".json";
that.http.get(storyUrl)
.map(res => res.json())
.subscribe(data => that.hnData = data,
err => that.logError(err),
() => console.log(that.hnData));
});
},
err => this.logError(err);
);
}
HTML
<ion-item *ngFor="#item of hnData">
{{item.title}}
</ion-item>
我认为嵌套可观察的 xhr 调用不是一个好习惯……但我不是这方面的专家,也不能告诉你为什么会出现这个异常(也许是关于这个 that
变量..).
但我有一个不同的方法来告诉你:
第一个组件 <top-stories>
加载 id 列表,然后为每个组件生成其他组件 <top-story>
:
@Component({
selector: 'top-stories',
providers: [],
template: '
<div>
<h2>Hacker news top stories:</h2>
<ul>
<li top-story *ngFor="#story; #i = index of list | async" [num]="i+1" [id]="story"></li>
</ul>
</div>
',
directives: [TopStory]
})
export class TopStories {
list: Observable<Array<number>>;
constructor(private http: Http) {
this.list = this.http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.map(list => list.slice(0, 30));
}
}
组件 <top-story>
自行加载 post 详细信息并显示:
@Component({
selector: '[top-story]',
providers: [],
template: `
<div>
<a *ngIf="item" [href]="item?.url">{{ num + ': ' + item?.title }}</a>
<span *ngIf="!item">loading...</span>
</div>
`,
directives: []
})
export class TopStory implements OnInit, OnDestroy {
@Input() num: Number;
@Input() id: Number;
sub: any;
item: object;
constructor(private http: Http) {}
ngOnInit() {
this.sub = this.http.get('https://hacker-news.firebaseio.com/v0/item/' + this.id + '.json')
.map(res => res.json())
.subscribe(item => this.item = item);
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
你可以在这个 plunker 中使用它:
http://plnkr.co/edit/BRMlyD?p=preview
我认为你可以用更 Rx-ish 的方式重写它:
getTopPost() {
return http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.mergeMap(list => Observable.fromArray(list))
.mergeMap(postId => http.get("https://hacker-news.firebaseio.com/v0/item/"+ postId +".json"))
.map(res => res.json())
}
我正在尝试 Angular 2 的 http GET 来检索 HackerNews 上的热门文章列表,之后我将在嵌套的可观察对象中检索它们各自的详细信息。
当我尝试循环显示 HTML 中的数据时遇到此错误。
Cannot find a differ supporting object '[object Object]'
此外,我猜应该有更好的方法来做到这一点,任何指示?
getTopPost() {
this.http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.subscribe(
data => {
data.map(function(postId){
let storyUrl = "https://hacker-news.firebaseio.com/v0/item/"+ postId +".json";
that.http.get(storyUrl)
.map(res => res.json())
.subscribe(data => that.hnData = data,
err => that.logError(err),
() => console.log(that.hnData));
});
},
err => this.logError(err);
);
}
HTML
<ion-item *ngFor="#item of hnData">
{{item.title}}
</ion-item>
我认为嵌套可观察的 xhr 调用不是一个好习惯……但我不是这方面的专家,也不能告诉你为什么会出现这个异常(也许是关于这个 that
变量..).
但我有一个不同的方法来告诉你:
第一个组件 <top-stories>
加载 id 列表,然后为每个组件生成其他组件 <top-story>
:
@Component({
selector: 'top-stories',
providers: [],
template: '
<div>
<h2>Hacker news top stories:</h2>
<ul>
<li top-story *ngFor="#story; #i = index of list | async" [num]="i+1" [id]="story"></li>
</ul>
</div>
',
directives: [TopStory]
})
export class TopStories {
list: Observable<Array<number>>;
constructor(private http: Http) {
this.list = this.http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.map(list => list.slice(0, 30));
}
}
组件 <top-story>
自行加载 post 详细信息并显示:
@Component({
selector: '[top-story]',
providers: [],
template: `
<div>
<a *ngIf="item" [href]="item?.url">{{ num + ': ' + item?.title }}</a>
<span *ngIf="!item">loading...</span>
</div>
`,
directives: []
})
export class TopStory implements OnInit, OnDestroy {
@Input() num: Number;
@Input() id: Number;
sub: any;
item: object;
constructor(private http: Http) {}
ngOnInit() {
this.sub = this.http.get('https://hacker-news.firebaseio.com/v0/item/' + this.id + '.json')
.map(res => res.json())
.subscribe(item => this.item = item);
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
你可以在这个 plunker 中使用它: http://plnkr.co/edit/BRMlyD?p=preview
我认为你可以用更 Rx-ish 的方式重写它:
getTopPost() {
return http.get('https://hacker-news.firebaseio.com/v0/topstories.json')
.map(res => res.json())
.mergeMap(list => Observable.fromArray(list))
.mergeMap(postId => http.get("https://hacker-news.firebaseio.com/v0/item/"+ postId +".json"))
.map(res => res.json())
}