Angular2 http.get()、map()、subscribe()および観察可能なパターン-基本的な理解


170

これで、3つのリンクがある最初のページができました。最後の「友達」リンクをクリックすると、適切な友達コンポーネントが開始されます。そこで、friends.jsonファイルに保存されている友達のリストを取得/取得したいと思います。今までのところ、すべてが正常に動作します。しかし、私はまだRxJのオブザーバブル、マップ、サブスクライブの概念を使用するangular2のHTTPサービスの初心者です。私はそれを理解しようとしていくつかの記事を読みましたが、実際の作業に入るまで、それらの概念を適切に理解するつもりはありません。

ここで私はすでにHTTP関連の仕事を除いて働いているplnkrを作りました。

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.

       }
  }

正しくガイドして説明してください。私はそれが多くの新しい開発者にとってとても有益であることを知っています。

回答:


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

次の2つの間違いを犯しました:

1-オブザーバブル自体をに割り当てましたthis.result。実際に友達のリストをに割り当てたい場合this.result。それを行う正しい方法は次のとおりです。

  • オブザーバブルを購読します。.subscribeオブザーバブルを実際に実行する関数です。次の3つのコールバックパラメータを使用します。

    .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- 2番目の間違いは、あなたがを呼び出し.json().map(res => res.json())後、オブザーバブルの成功コールバックで再度呼び出しました。 .map()結果.json()は、成功のコールバックに渡される前に(あなたの場合は)返すものに変換するトランスフォーマーで、どちらかで一度呼び出す必要があります。


2
ここであなたのプランカーを行きます。行を変更しました:myfriends.tsで
21、23

1
私が理解できなかったのは、なぜここで「マップ」機能を使用するのかということです。結果に対して.jsonを呼び出すだけです。そうすることの利点は何ですか?
rubmz

5
あなたは正しい@rubmzです。私の回答で述べたように、それを行うことができますが、1つの大きな利点はロジックを分離することです たとえば、サービスに関数がありますgetFriends(){return http.get('friends.json').map(r => r.json());}。これで、毎回getFriends().subscribe(...)呼び出す必要なく、呼び出すことができます.json()
Abdulrahman Alsoghayer

2
はい、これは初心者には少し混乱します。その不思議なmap()が何をして何をしないか...しかし、ついに私もそれを手に入れました:)
rubmz

1
@Abdulrahman、多分あなたもこの質問を見ているために興味を持つだろう:stackoverflow.com/questions/40505691/...
nyluje

138

概念

Observablesは、非同期の処理とイベントに取り組みます。これをpromiseと比較すると、observables = promises + eventsと表現できます。

オブザーバブルの優れている点は、それらが遅延していること、それらをキャンセルでき、それらにいくつかの演算子(などmap)を適用できることです。これにより、非同期のものを非常に柔軟に処理できます。

オブザーバブルの最高のパワーを説明する優れたサンプルは、フィルター入力を対応するフィルター済みリストに接続する方法です。ユーザーが文字を入力すると、リストが更新されます。Observableは対応するAJAXリクエストを処理し、別のリクエストが入力の新しい値によってトリガーされた場合、以前の進行中のリクエストをキャンセルします。これが対応するコードです:

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

textValueはフィルター入力に関連付けられたコントロールです)。

このようなユースケースのより広い説明は次のとおりです。Angular2でフォームの変更を監視する方法は?

AngularConnect 2015とEggHeadでは2つの素晴らしいプレゼンテーションがあります。

Christoph Burgdorfはこの件に関していくつかの素晴らしいブログ投稿も書いています:

実行中

実際、あなたのコードに関して、あなたは2つのアプローチを混合しました;-)ここにそれらがあります:

  • オブザーバブルを自分で管理します。この場合、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();
       }
    }
    

    getmapメソッドの両方からの戻り値は、(promiseの場合と同じように)結果ではなく監視可能です。

  • 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

私はあなたのコードに関する詳細で私の答えを更新しました。それがお役に立てば幸いです;-)
ティエリーテンプリエ2016年

申し訳ありませんがお答えできませんでした。より明確ですが、受け入れられて高く評価された回答は、私の質問について十分に理解するのに役立ちました。しかし、うまくいけば、より詳細な説明があるので、あなたはあなたの明確な答えのために良いヒットを得るでしょう。基本的な過小評価のための回答も受け入れました。
micronyks 2016年

2
ティエリーテンプリエこれは素晴らしい答えですが、1つははっきりしていません。はいの場合、どうしてthis.resultに送信するのですか?それらは異なるタイプです。
Stav Alfi

@StavAlfi pipesobservablesです。詳細については、thierryによって提案されたこの動画を確認してください: youtube.com/watch? v=bVI5gGTEQ_U。
candidJ 2016

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

HttpClient APIはバージョン4.3.0で導入されました。これは既存のHTTP APIを進化させたもので、独自のパッケージ@ angular / common / httpを持っています。最も注目すべき変更の1つは、応答オブジェクトがデフォルトでJSONであるため、mapメソッドで解析する必要がなくなったことです。すぐに以下のように使用できます。

http.get('friends.json').subscribe(result => this.result =result);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.