web-dev-qa-db-fra.com

Angular2 http.get (), map (), subscribe () et modèle observable - compréhension de base

Maintenant, j'ai une première page où j'ai trois liens. Une fois que vous avez cliqué sur le dernier lien "amis", le composant amis approprié est lancé. Là, je veux chercher/obtenir la liste de mes amis bloqués dans le fichier friends.json. Jusqu'à présent, tout fonctionne bien. Mais je suis toujours un débutant pour le service HTTP d'angular2 en utilisant le concept observable, map, subscribe de RxJs. J'ai essayé de comprendre et de lire quelques articles, mais jusqu'à ce que je me lance dans la pratique, je ne comprendrai pas bien ces concepts.

Ici, j'ai déjà fait plnkr qui fonctionne sauf le travail lié à HTTP.

Plnkr

myfriends.ts

 import {Component,View,CORE_DIRECTIVES} from 'angular2/core';
 import {Http, Response,HTTP_PROVIDERS} from 'angular2/http';
 import 'rxjs/Rx';
 @Component({
    template: `
    <h1>My Friends</h1>
    <ul>
      <li *ngFor="#frnd of result">
          {{frnd.name}} is {{frnd.age}} years old.
      </li>
    </ul>
    `,
    directive:[CORE_DIRECTIVES]
  })

  export class FriendsList{

      result:Array<Object>; 
      constructor(http: Http) { 
        console.log("Friends are being called");

       // below code is new for me. So please show me correct way how to do it and please explain about .map and .subscribe functions and observable pattern.

        this.result = http.get('friends.json')
                      .map(response => response.json())
                      .subscribe(result => this.result =result.json());

        //Note : I want to fetch data into result object and display it through ngFor.

       }
  }

S'il vous plaît guider et expliquer correctement. Je sais que cela sera tellement bénéfique pour beaucoup de nouveaux développeurs.

164
nyks

Voici où vous vous êtes trompé:

this.result = http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result.json());

cA devrait etre:

http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result);

ou

http.get('friends.json')
                  .subscribe(result => this.result =result.json());

Vous avez commis deux erreurs:

1- Vous avez assigné l'observable lui-même à this.result. Quand vous vouliez réellement assigner la liste d'amis à this.result. La bonne façon de le faire est:

  • vous vous abonnez à l'observable. .subscribe est la fonction qui exécute l'observable. Il faut trois paramètres de rappel comme suit:

    .subscribe(success, failure, complete);

par exemple:

.subscribe(
    function(response) { console.log("Success Response" + response)},
    function(error) { console.log("Error happened" + error)},
    function() { console.log("the subscription is completed")}
);

Généralement, vous récupérez les résultats du rappel de succès et vous les affectez à votre variable. le rappel d'erreur est explicite. le rappel complet est utilisé pour déterminer que vous avez reçu les derniers résultats sans erreur. Sur votre plunker, le rappel complet sera toujours appelé après le rappel réussi ou le rappel d'erreur.

2- La deuxième erreur, vous avez appelé .json() sur .map(res => res.json()), puis vous l'avez rappelée lors du rappel de réussite de l'observable. .map() est un transformateur qui transformera le résultat en ce que vous retournerez (dans votre cas, .json()) avant qu'il ne soit transmis au rappel de succès, vous devriez l'appeler une fois pour l'un ou l'autre.

199
Abdulrahman

Concepts

Observables en bref aborde le traitement et les événements asynchrones. En comparant les promesses, cela pourrait être décrit comme observables = promesses + événements.

Ce qui est génial avec les observables, c’est qu’ils sont paresseux, qu’ils peuvent être annulés et que vous pouvez y appliquer des opérateurs (comme map, ...). Cela permet de gérer les choses asynchrones de manière très flexible.

Un excellent exemple décrivant au mieux la puissance des observables permet de connecter une entrée de filtre à une liste filtrée correspondante. Lorsque l'utilisateur entre des caractères, la liste est actualisée. Les observables traitent les requêtes AJAX correspondantes et annulent les requêtes en cours précédentes si une autre est déclenchée par une nouvelle valeur dans l'entrée. Voici le code correspondant:

this.textValue.valueChanges
    .debounceTime(500)
    .switchMap(data => this.httpService.getListValues(data))
    .subscribe(data => console.log('new list values', data));

(textValue est la commande associée à l'entrée du filtre).

Voici une description plus large de ce cas d'utilisation: Comment surveiller les changements de forme dans Angular 2? .

Il y a deux excellentes présentations à AngularConnect 2015 et à EggHead:

Christoph Burgdorf a également écrit d'excellents billets de blog sur le sujet:

En action

En fait, en ce qui concerne votre code, vous avez mélangé deux approches ;-) Les voici:

  • Gérez l'observable par vous-même . Dans ce cas, vous devez appeler la méthode subscribe sur l'observable et affecter le résultat à un attribut du composant. Vous pouvez ensuite utiliser cet attribut dans la vue pour parcourir la collection:

    @Component({
      template: `
        <h1>My Friends</h1>
        <ul>
          <li *ngFor="#frnd of result">
            {{frnd.name}} is {{frnd.age}} years old.
          </li>
        </ul>
      `,
      directive:[CORE_DIRECTIVES]
    })
    export class FriendsList implement OnInit, OnDestroy {
      result:Array<Object>; 
    
      constructor(http: Http) {
      }
    
      ngOnInit() {
        this.friendsObservable = http.get('friends.json')
                      .map(response => response.json())
                      .subscribe(result => this.result = result);
       }
    
       ngOnDestroy() {
         this.friendsObservable.dispose();
       }
    }
    

    Les retours des deux méthodes get et map sont observables et non le résultat (de la même manière qu'avec les promesses).

  • Laissons gérer l'observable par le template Angular . Vous pouvez également utiliser le canal async pour gérer implicitement l'observable. Dans ce cas, il n'est pas nécessaire d'appeler explicitement la méthode subscribe.

    @Component({
      template: `
        <h1>My Friends</h1>
        <ul>
          <li *ngFor="#frnd of (result | async)">
            {{frnd.name}} is {{frnd.age}} years old.
          </li>
        </ul>
      `,
      directive:[CORE_DIRECTIVES]
    })
    export class FriendsList implement OnInit {
      result:Array<Object>; 
    
      constructor(http: Http) {
      }
    
      ngOnInit() {
        this.result = http.get('friends.json')
                      .map(response => response.json());
       }
    }
    

Vous pouvez remarquer que les observables sont paresseux. La requête HTTP correspondante ne sera donc appelée qu'une fois par un auditeur auquel est attachée la méthode subscribe.

Vous pouvez également remarquer que la méthode map est utilisée pour extraire le contenu JSON de la réponse et l’utiliser ensuite dans le traitement des données observables.

J'espère que cela vous aide, Thierry

135
Thierry Templier
import { HttpClientModule } from '@angular/common/http';

L'API HttpClient a été introduite dans la version 4.3.0. C'est une évolution de l'API HTTP existante et a son propre paquet @ angular/common/http. L’un des changements les plus remarquables est que l’objet de réponse est maintenant un JSON par défaut. Il n’est donc plus nécessaire de l’analyser avec la méthode map.

http.get('friends.json').subscribe(result => this.result =result);
11
rajesh kumar