typescript - Angular 2 uppdatera komponentvariabel med http-tjänst promise


Jag håller för närvarande på att lära mig Angular 2 och TypeScript vilket verkar gå bra hittills, men jag har lite problem med att få min service som jag skapade att uppdatera arrayen i komponenten jag anropar den i, även om all data från servicen visas korrekt i ng-for i min template.

    ***people-service.ts***

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

/*
  Generated class for the PeopleService provider.

  See https://angular.io/docs/ts/latest/guide/dependency-injection.html
  for more info on providers and Angular 2 DI.
*/
@Injectable()
export class PeopleService {
  constructor(public http: Http) {

  }

  load() {
    return new Promise(resolve => {
      this.http.get('http://api.randomuser.me/?page=3&results=30')
        .map(res => res.json())
        .subscribe(data => {
          data = data.results;
          resolve(data);
        });
    });
  }

}

Ovan är tjänsten jag skapade som returnerar JSON-data i ett löfte från API:et.

***about.ts***
import { Component, ViewChild, ElementRef } from '@angular/core';

import { NavController, Content } from 'ionic-angular';
import { PeopleService } from '../../providers/people-service';

@Component({
    selector: 'page-about',
    templateUrl: 'about.html',
    providers: [PeopleService]
})
export class AboutPage {

    public people: any;

    constructor(public navCtrl: NavController, public peopleService: PeopleService) {
        this.peopleService.load().then(data => {
            this.people = data;
        });
        console.log(this.people);
    }
}

I ovanstående komponent laddar jag datan i min konstruktor som visas i mallen fint som jag sa men console.log(this.people) visar undefined. Jag hoppas att någon kan hjälpa mig att lista ut vad jag saknar här. Jag kan tänka mig att jag måste göra något fel med sättet datan returneras från tjänsten eller på den punkt där jag försöker logga datan. För den som är intresserad är huvudmålet med detta att göra this.people/2 för att få det mittersta objektet i arrayen och scrolla till det när sidan laddas.

Svar #1

this.peopleService.load() är en asynkron funktion, vilket betyder:

  1. Funktionen load() körs
  2. console.log körs
  3. data returneras från servern och this.people=data körs.

Du vill sätta console.log inuti load()-callbackfunktionen, där this.people=data sätts, så att du kan skriva ut de faktiska uppgifterna, på detta sätt:

this.peopleService.load().then(data => {
    this.people = data;
    console.log(this.people);
});

Svar #2

Försök att undvika att slå in Observables i Promises, eller Promises i Observables och skriv dina servicemetoder så att de returnerar en Observable. (Om du inte har en riktigt bra anledning att göra det :)

@Injectable()
export class PeopleService {
  constructor(public http: Http) { }

  load() {
    // DON'T 
    return new Promise(resolve => {
      this.http.get('http://api.randomuser.me/?page=3&results=30')
        .map(res => res.json())
        .subscribe(data => {
          data = data.results;
          resolve(data);
        });
    });
    // DO: 
    return this.http.get('http://api.randomuser.me/?page=3&results=30')
      .map(res => res.json())
  }

}

I tjänsten ställer du upp ett sätt att hämta datan, och i din komponent (där du faktiskt behöver datan) prenumererar du på det observerbara som returneras av tjänsten för att få datan:

export class AboutPage {
    public people: any;

    constructor(public navCtrl: NavController, public peopleService: PeopleService) {
        this.peopleService.load().subscribe(data => {
            this.people = data;
            console.log(this.people);
        });
    }
}

Relaterade artiklar