2016-01-07 165 views
8

我正在尝试Angular 2的http GET来检索HackerNews上的顶级文章列表,之后我将在嵌套的observable中检索它们各自的细节。Angular 2中的嵌套Observable

我试图循环显示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> 

回答

5

我不认为这是一个很好的做法,巢观察到XHR调用......但我不是一个关于它的专家,不能告诉你为什么你有这个例外(可能是关于这个that var ..)。

但我有不同的方法来告诉你:

第一分量<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>负载本身发布细节并显示它:

@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(); 
    } 
} 

你可以在这个运动中玩它: http://plnkr.co/edit/BRMlyD?p=preview

+0

但为什么不是一个好的做法,以嵌套的呢?我有一个问题,因为我嵌套到http.get返回两个可观察的,我想它有像承诺(解决第一次调用,然后做第二次),但我得到一些未定义的参数,如我在另一个范围。 – mautrok

+0

我真的不认为嵌套可观察的xhr调用是不好的,但不好的是嵌套订阅(订阅另一个可观察订阅内的观察值)。你必须使用'flatMap','concatMap'等操作符,并且只需一次订阅它。 – bertrandg

16

我觉得你可以在一个更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()) 
}