Angular2 http.get (), map (), передплатити () та спостережуваний шаблон - основне розуміння


170

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

Тут я вже зробив plnkr, який працює, крім роботи, пов’язаної з HTTP.

Плнкр

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.

       }
  }

Будь ласка, керуйте та поясніть належним чином. Я знаю, що це буде так вигідно для багатьох нових розробників.

Відповіді:


205

Ось де ви помилилися:

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

Зазвичай ви берете результати від успішного зворотного виклику і присвоюєте їм свою змінну. Зворотний виклик помилки не пояснює. повний зворотний виклик використовується для визначення того, що ви отримали останні результати без будь-яких помилок. У вашому планкері повний зворотний дзвінок завжди буде викликаний після успіху чи зворотного виклику помилки.

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


2
ось ви йдете на ваш плункер . Я змінив рядки: 21, 23 на myfriends.ts
Abdulrahman Alsoghayer

1
Що я не зрозумів, це чому взагалі використовувати функцію "карта"? Ми могли просто зателефонувати .json за результатом. То яка ж користь від цього?
rubmz

5
Ви праві @rubmz. Ви могли це зробити, як я вже згадував у своїй відповіді. Але одна величезна перевага - це розділення логіки. Наприклад, у вашій службі у вас є функція getFriends(){return http.get('friends.json').map(r => r.json());}. Тепер ви можете телефонувати getFriends().subscribe(...)без необхідності дзвонити .json()кожен раз.
Абдулрахман Тесґайер

2
Так, для новачків це лише трохи заплутано. Що ця таємнича карта () робить, а що ні ... Але нарешті я це теж отримав :)
rubmz

1
@Abdulrahman, можливо , вам буде цікаво поглянути на це питання теж: stackoverflow.com/questions/40505691 / ...
nyluje

138

Поняття

Спостерігається в коротких вирішеннях асинхронної обробки та подій. У порівнянні з обіцянками це можна було б описати як спостережувані = обіцянки + події.

Що спостерігається у спостережуваних, це те, що вони ліниві, їх можна скасувати, і ви можете застосувати в них деякі оператори (наприклад 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методів є спостережуваним не результатом (так само, як і при обіцянках).

  • Нехай керує спостережуваним шаблоном 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 з відповіді та використання його при обробці, що спостерігається.

Сподіваюся, це допоможе тобі, Тьєррі


Дякую за всі довідки. Але чи можете ви мені допомогти з моїм планком?
nyks

Я оновив свою відповідь більш детально стосовно вашого коду. Сподіваюся, це допоможе вам ;-)
Тіррі Темплієр

вибачте, що я не міг прийняти вашу відповідь. Більш чітка, але прийнята і вдячна відповідь допомогла мені досить зрозуміти моє запитання. Але, сподіваємось, ви отримаєте хороші враження за свою чітку відповідь, оскільки у вас буде більш детальне пояснення. Відповідь прийнята теж для гарного базового заниження.
мікроніки

2
Thierry Templier - це відмінна відповідь, але одне мені незрозуміло, я торкнувся http.get ('friends.json'). Якщо так, то як ви надішліть його на this.result? вони різні типи.
Став Алфі

@StavAlfi pipesтакож є observables. перегляньте це відео: youtube.com/watch?v=bVI5gGTEQ_U, запропонований Thierry для отримання додаткової інформації.
відвертийJ

11
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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.