Подтвердить что ты не робот

Цепочка RxJS Наблюдаемые данные http из Angular2 с TypeScript

В настоящее время я пытаюсь научить себя Angular2 и TypeScript после счастливой работы с AngularJS 1. * в течение последних 4 лет! Я должен признать, что я его ненавижу, но я уверен, что мой момент в eureka не за горами... во всяком случае, я написал службу в своем фиктивном приложении, которое будет получать данные HTTP из фальшивого бэкэнда, который я написал, который служит JSON.

import {Injectable} from 'angular2/core';
import {Http, Headers, Response} from 'angular2/http';
import {Observable} from 'rxjs';

@Injectable()
export class UserData {

    constructor(public http: Http) {
    }

    getUserStatus(): any {
        var headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.get('/restservice/userstatus', {headers: headers})
            .map((data: any) => data.json())
            .catch(this.handleError);
    }

    getUserInfo(): any {
        var headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.get('/restservice/profile/info', {headers: headers})
            .map((data: any) => data.json())
            .catch(this.handleError);
    }

    getUserPhotos(myId): any {
        var headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.get(`restservice/profile/pictures/overview/${ myId }`, {headers: headers})
            .map((data: any) => data.json())
            .catch(this.handleError);
    }

    private handleError(error: Response) {
        // just logging to the console for now...
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }   
}

Теперь в компоненте я хочу запускать (или цепочки) методы getUserInfo() и getUserPhotos(myId). В AngularJS это было легко, как в моем контроллере, я бы сделал что-то подобное, чтобы избежать "пирамиды гибели"...

// Good old AngularJS 1.*
UserData.getUserInfo().then(function(resp) {
    return UserData.getUserPhotos(resp.UserId);
}).then(function (resp) {
    // do more stuff...
}); 

Теперь я попытался сделать что-то подобное в моем компоненте (заменив .then на .subscribe), однако моя консоль ошибок сходит с ума!

@Component({
    selector: 'profile',
    template: require('app/components/profile/profile.html'),
    providers: [],
    directives: [],
    pipes: []
})
export class Profile implements OnInit {

    userPhotos: any;
    userInfo: any;

    // UserData is my service
    constructor(private userData: UserData) {
    }

    ngOnInit() {

        // I need to pass my own ID here...
        this.userData.getUserPhotos('123456') // ToDo: Get this from parent or UserData Service
            .subscribe(
            (data) => {
                this.userPhotos = data;
            }
        ).getUserInfo().subscribe(
            (data) => {
                this.userInfo = data;
            });
    }

}

Я, очевидно, что-то делаю неправильно... как мне лучше всего с Observables и RxJS? Извините, если я задаю глупые вопросы... но спасибо за помощь заранее! Я также заметил повторный код в своих функциях при объявлении заголовков http...

4b9b3361

Ответ 1

В вашем случае использования, я думаю, что оператор flatMap - это то, что вам нужно:

this.userData.getUserPhotos('123456').flatMap(data => {
  this.userPhotos = data;
  return this.userData.getUserInfo();
}).subscribe(data => {
  this.userInfo = data;
});

Таким образом, вы будете выполнять второй запрос после получения первого. Оператор flatMap особенно полезен, если вы хотите использовать результат предыдущего запроса (предыдущее событие) для выполнения другого. Не забудьте импортировать оператора, чтобы иметь возможность использовать его:

import 'rxjs/add/operator/mergeMap';

Этот ответ может дать вам более подробную информацию:

Если вы хотите использовать только метод subscribe, вы используете что-то вроде этого:

this.userData.getUserPhotos('123456')
    .subscribe(
      (data) => {
        this.userPhotos = data;

        this.userData.getUserInfo().subscribe(
          (data) => {
            this.userInfo = data;
          });
      });

Чтобы закончить, если вы хотите выполнить оба запроса параллельно и получать уведомление, когда все результаты будут затем, вы должны рассмотреть возможность использования Observable.forkJoin (вам нужно добавить import 'rxjs/add/observable/forkJoin'):

Observable.forkJoin([
  this.userData.getUserPhotos(),
  this.userData.getUserInfo()]).subscribe(t=> {
    var firstResult = t[0];
    var secondResult = t[1];
});