2016-01-07 11 views
8

Sto provando l'http GET di Angular 2 per recuperare un elenco di articoli principali su HackerNews e dopo di che recupererò i rispettivi dettagli in un osservabile nidificato.Nested Observable in Angular 2

Ho riscontrato questo errore quando tento di eseguire il ciclo e visualizzare i dati nel mio codice HTML.

non riesce a trovare un diverso supporto oggetto '[object Object]'

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

Inoltre, sto indovinando ci dovrebbe essere un modo migliore per fare questo, qualsiasi puntatore?

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> 

risposta

5

non credo che sia una buona pratica per nidificare le chiamate XHR osservabile ... ma io non sono un esperto su di esso e non si può dire perché hai questa eccezione (forse su questo that var ..).

Ma ho un approccio diverso visualizzare:

Un primo componente <top-stories> caricare l'elenco id e quindi generare altri componenti <top-story> per ciascuno di essi:

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

Il componente <top-story> carico stesso inviare i dettagli e mostralo:

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

Puoi giocare con questo plunker: http://plnkr.co/edit/BRMlyD?p=preview

+0

ma perché non è una buona pratica per annidato loro? Ho un problema perché sto nidificando su http.get che restituisce due osservabili, sto provando ad avere qualcosa come la promessa (risolvi prima la chiamata poi esegui la seconda) ma ottengo alcuni parametri indefiniti come se fossi in un altro ambito . – mautrok

+0

Non penso che sia davvero male fare il nesting delle chiamate xhr osservabili, ma ciò che è male è annidare le sottoscrizioni (iscriversi ad un osservabile all'interno di un altro abbonamento osservabile). Devi usare operatori come 'flatMap',' concatMap', .. e iscriverti solo una volta. – bertrandg

16

penso che si può riscrivere in modo più Rx-ish come questo:

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