web-dev-qa-db-fra.com

Faire exécuter la fonction par le composant après la fin de l'appel du service http.get

J'ai vraiment du mal à m'enrouler autour des observables et des abonnements dans angular2. Le problème que j'ai actuellement est le suivant:

J'ai un service qui contient des méthodes pour publier et obtenir des données à partir d'une API. Le service est injecté dans un composant, qui appelle directement ces méthodes dans le service. Le service récupère ensuite les données et les stocke lui-même, mais je souhaite ensuite traiter ces données dans le composant. Je ne peux pas trouver comment faire exécuter une fonction par le composant après que le service a récupéré et stocké les données lui-même.

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
    }
}
11
Peter Trotman

Pour répondre à ma propre question:

Dans la racine de l'application, importez Rxjs avec:

import 'rxjs/Rx';

Cela vous donne accès à l'objet Observable complet (et pas seulement à l'Observable-lite inclus avec Angular). Cela vous permet de .map .reduce etc. les requêtes Http.

Vous pouvez désormais utiliser .map sur une requête Http pour exécuter du code arbitraire dans le contexte du service, même si c'est le composant qui souscrit au résultat. Donc, pour réaliser ce que je voulais faire au début, nous pouvons:

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

Merci à Gunter et Mark pour les réponses, m'a aidé à comprendre un peu cela et j'ai l'impression de mieux comprendre Observables après avoir traversé beaucoup de documents pour résoudre ce problème!

5
Peter Trotman

Vérifiez si le résultat est déjà arrivé, si oui, créez une nouvelle promesse et complétez-la avec le résultat, non, récupérez-la et renvoyez-la également comme promesse.

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

Je ne connais pas TS et ce code peut contenir des erreurs (j'utilise Angular seulement Dart), mais vous devriez avoir l'idée.

Voir également
- http://blog.oughttram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

2
Günter Zöchbauer

Cela peut se produire simplement avec les méthodes Rxjs, voici un moyen simple et classique d'appeler les services une fois l'application chargée, puis nous pouvons l'abonner en plusieurs composants. Assurez-vous que les services doivent être réutilisables pour tous les composants, alors faites comme vous pouvez faire du code dans les services et mappez, abonnez-vous uniquement dans le composant:

Services:

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

Composant

 export class Component {
    formattedResult: Object;

    constructor(private service: Service) { }

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

Eh bien, vous pouvez utiliser une fonction de rappel dans ce cas,

En prenant l'exemple, considérez que c'est la fonction post qui déclenche le service post dans le module de service

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

Notez ici la fonction consoleMyOutput(). Cela sera déclenché une fois la réponse obtenue après l'appel du service

Maintenant,

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

Cette fonction sera déclenchée juste après cela.

0
Ranjan kumar