2016-01-07 16 views
8

Próbuję http GET od Angular 2, aby pobrać listę najlepszych artykułów na temat HackerNews, a następnie pobiorę ich odpowiednie szczegóły w zagnieżdżonej obserwowalnej.Zagnieżdżone obserwowalne w Angular 2

Występuje ten błąd podczas próby zapętlenia i wyświetlenia danych w moim kodzie HTML.

nie może znaleźć się różnić wspieranie przedmiotu '[object Object]'

Cannot find a differ supporting object '[object Object]'

Również jestem zgadywania nie powinno być lepszym sposobem, aby to zrobić, każdy wskaźnik?

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> 

Odpowiedz

5

Nie sądzę, że jest to dobra praktyka, aby gniazdo nazywa obserwowalne XHR ... ale nie jestem ekspertem o tym i nie mogę powiedzieć, dlaczego masz ten wyjątek (może o tym that var ..).

Ale mam inne podejście pokazać:

pierwszym <top-stories> załadować listę identyfikator komponentu, a następnie wygenerować innym składnik <top-story> dla każdego z nich:

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

komponentu <top-story> obciążenie sam słupek szczegóły i pokaż go:

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

Możesz grać z nim w tym plunker: http://plnkr.co/edit/BRMlyD?p=preview

+0

ale dlaczego nie jest to dobra praktyka, aby je zagnieżdżać? Mam problem, ponieważ zagnieżdżam się do http.get, który zwraca dwie obserwowalne, próbuję mieć coś podobnego do obietnicy (najpierw rozwiązać drugie połączenie), ale dostaję niezdefiniowane parametry, jakbym był w innym zakresie . – mautrok

+0

Naprawdę nie sądzę, że źle jest zagnieżdżać obserwowalne wywołania xhr, ale złe jest to, aby zagnieździć subskrypcje (zasubskrybuj to, co można zaobserwować w innej obserwowalnej subskrypcji). Musisz używać operatorów takich jak 'flatMap',' concatMap', .. i subskrybować go tylko jeden raz. – bertrandg

16

myślę, że można przerobić go w bardziej Rx-owski sposób jak poniżej:

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