Функция выполнения компонента после завершения обслуживания http.get

У меня возникают настоящие проблемы, обворачивающие мои наблюдатели и подписки в angular2. В настоящее время проблема заключается в следующем:

У меня есть служба, которая содержит методы для публикации и получения данных из API. Услуга вводится в компонент, который напрямую вызывает эти методы в службе. Затем служба извлекает данные и сохраняет их сама, но затем я хочу обработать эти данные внутри компонента. Я не могу понять, как выполнить компонент после выполнения службы и сохранить данные.

service.ts

import { Injectable } from 'angular2/core';    
import { Http } from 'angular2/router';

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        return this.http.get(url).subscribe(
            result => this.result = result.json(),
            error => console.log(error),
            () => {}
        )
    }
}

component.ts

import { Component } from 'angular2/core';
import { Service } from './service';

@Component({
    ...
})
export class Component {
    formattedResult: Object;

    constructor(service: Service) {
        this.service = service;
        this.service.httpGet('/api')

        // How do I call format result on service.result only after it is completed?
        this.formatResult(service.result) // Need to execute this after the http call is completed

        // I want something like:
        this.service.httpGet('/api').then(() => formatResult(this.service.result));
    }

    formatResult(result) {
        this.formattedResult = result.map(x => x.length) // For example
    }
}

Ответ 1

Чтобы ответить на мой собственный вопрос:

В корне приложения импортируйте Rxjs с помощью:

import 'rxjs/Rx';

Это дает вам доступ к полному объекту Observable (а не только к "Observable-lite", включенному в Angular). Это позволяет вам .map.reduce и т.д. Запросы Http.

Теперь вы можете использовать .map для запроса Http для выполнения произвольного кода в контексте службы, даже если это компонент, который подписывается на результат. Поэтому для достижения того, что я намеревался сделать в начале, мы можем:

service.ts

import { Injectable } from 'angular2/core';    
import { Http } from 'angular2/router';

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        return this.http.get(url).map(
            result => {
                let data = result.json();
                this.result = data;
                return data
            }
        )
    }
}

component.ts

import { Component } from 'angular2/core';
import { Service } from './service';

@Component({
    // Component setup
})
export class Component {
    formattedResult: Object;

    constructor(service: Service) {
        this.service = service;
        this.service.httpGet('/api').subscribe(
            data => this.formatResult(data);
        );
    }

    formatResult(result) {
        this.formattedResult = result.map(x => x.length) // For example
    }
}

Спасибо Гюнтеру и Марку за ответы, помогли мне немного обернуть мою голову, и я чувствую, что понимаю, что Observables намного лучше прошли через многие документы, решая эту проблему!

Ответ 2

Проверьте, пришел ли результат, если да, создайте новое обещание и завершите его результатом, а не извлеките его, и верните его как обещание.

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        if(result === undefined) {
          return this.http.get(url).toPromise().then(
              result => this.result = result.json(),
              error => console.log(error);
          );
        } else {
          return new Promise().resolve(result);
        }
    }
}

Я не знаю TS, и этот код может содержать некоторые ошибки (я использую только Angular только Dart), но вы должны получить эту идею.

См. также
- http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

Ответ 3

Ну, в этом случае вы могли бы использовать функцию обратного вызова,

Пример подумайте, что это функция post, которая запускает почтовую службу в сервисном модуле

postData(id: string, name: string) {
    console.log("Got you",id);
  this._employeeService.postServices({id: id, name: name})
    .subscribe(
      (response:Response) => this.consoleMyOutput(),
      error => console.log(error)
    );  
}

Здесь обратите внимание на функцию consoleMyOutput(). Это будет срабатывать после получения ответа после того, как служба была вызвана

Теперь,

consoleMyOutput(){console.log("Write Your call back function")};

Эта функция будет запущена сразу после этого.

Ответ 4

Это может произойти просто с методами Rxjs, вот простой и классический способ вызова сервисов один раз после загрузки приложения, после чего мы можем подписать его на несколько компонентов. Убедитесь, что сервисы должны быть многократно использованы для всех компонентов, поэтому делайте то, что вы можете делать в сервисах и на карте, подписывайтесь только в компоненте:

Услуги:

 import { Injectable } from 'angular2/core';    
 import { Http } from 'angular2/http';

 @Injectable()
 export class Service {
     result: Object;

     constructor(private http: Http) {}

     private _urlGet = '/api';

     httpGet(){
        return this.http.get(this._urlGet)
          .map(res => JSON.parse(res.json()))
          .do(result => {
             this.result = result;
           }, error => console.log(error))
     }
  }

Составная часть

 export class Component {
    formattedResult: Object;

    constructor(private service: Service) { }

    ngOnInit(){
       this.service.httpGet().subscribe(result => {
          this.formattedResult = result;
       }
    }
 }

Ответ 5

Вы можете использовать Angular Route Resolvers. Это будет выполнено перед загрузкой компонента.

https://angular.io/api/router/Resolve