Angular2 http.get(), map(), subscribe() и наблюдаемый шаблон - базовое понимание

Теперь у меня есть начальная страница, где у меня есть три ссылки. После того, как вы нажмете на последнюю ссылку "друзья", начнут инициироваться соответствующие друзья. Там, Я хочу получить/получить список моих друзей в файле friends.json. До сих пор все работает нормально. Но я все еще новичок в сервисе angular2 HTTP, используя RxJs, наблюдаемые, отображающие карту, подписку. Я попытался понять это и прочитать несколько статей, но пока я не получу практическую работу, я не буду правильно понимать эти понятия.

Здесь я уже сделал plnkr, который работает, кроме работы, связанной с 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.

       }
  }

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

Ответ 1

Вот где вы поступили не так:

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

это должно быть:

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

или

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

Вы допустили две ошибки:

1- Вы назначили наблюдаемое значение this.result. Когда вы действительно хотели назначить список друзей this.result. Правильный способ сделать это:

  • вы подписываетесь на наблюдаемое. .subscribe - это функция, которая фактически выполняет наблюдаемое. Требуется три параметра обратного вызова:

    .subscribe(success, failure, complete);

например:

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

Обычно вы берете результаты от обратного вызова успеха и назначаете его переменной. обратный вызов ошибки сам по себе. полный обратный вызов используется для определения того, что вы получили последние результаты без каких-либо ошибок. На вашем плунтере, полный обратный вызов будет всегда вызываться после успешного или обратного вызова.Забастовкa >

2- Вторая ошибка, вы назвали .json() на .map(res => res.json()), после чего вы снова вызвали ее на обратном вызове успеха наблюдаемого. .map() - это трансформатор, который преобразует результат в то, что вы возвращаете (в вашем случае .json()), прежде чем он перейдет на обратный вызов успеха вы должны называть его один раз на одном из них.

Ответ 2

Основные понятия

Наблюдаемые в коротких задачах асинхронная обработка и события. По сравнению с promises это можно описать как наблюдаемые = promises + события.

Что отлично с наблюдаемыми, так это то, что они ленивы, их можно отменить, и вы можете применить к ним некоторые операторы (например, map,...). Это позволяет обрабатывать асинхронные вещи очень гибким способом.

Отличный пример, описывающий наилучшую силу наблюдаемых, - это способ подключения входа фильтра к соответствующему отфильтрованному списку. Когда пользователь вводит символы, список обновляется. Наблюдаемые обрабатывают соответствующие запросы AJAX и отменяют предыдущие запросы на выполнение, если другое инициируется новым значением на входе. Вот соответствующий код:

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

(textValue - это элемент управления, связанный с входом фильтра).

Вот более подробное описание такого варианта использования: Как посмотреть изменения формы в Angular 2?.

В AngularConnect 2015 и EggHead есть две отличные презентации:

Кристоф Бургдорф также написал несколько замечательных постов в блоге по теме:

В действии

На самом деле в отношении вашего кода вы смешивали два подхода:-) Вот они:

  • Управлять наблюдаемым вашим собственным. В этом случае вы отвечаете за вызов метода subscribe для наблюдаемого и присваиваете результат атрибуту компонента. Затем вы можете использовать этот атрибут в представлении для итерации по коллекции:

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

    Возврат из методов get и map является наблюдаемым не результатом (таким же образом, как с promises).

  • Позвольте управлять наблюдаемым шаблоном Angular. Вы также можете использовать канал async для неявного управления наблюдаемым. В этом случае нет необходимости явно вызывать метод 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());
       }
    }
    

Вы можете заметить, что наблюдаемые ленивы. Таким образом, соответствующий HTTP-запрос будет вызываться только после прослушивателя с прикрепленным к нему с помощью метода subscribe.

Вы также можете заметить, что метод map используется для извлечения содержимого JSON из ответа и использования его в наблюдаемой обработке.

Надеюсь, это поможет вам, Thierry

Ответ 3

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

API HttpClient был представлен в версии 4.3.0. Это эволюция существующего HTTP API и имеет собственный пакет @angular/common/http. Одним из наиболее заметных изменений является то, что теперь объектом ответа является JSON по умолчанию, поэтому нет необходимости разбирать его с помощью метода карты. Вплоть отсюда мы можем использовать, как показано ниже

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