Angular2 http.get (), map (), berlangganan () dan pola yang dapat diamati - pemahaman dasar


170

Sekarang, saya memiliki halaman awal di mana saya memiliki tiga tautan. Setelah Anda mengklik tautan 'teman' terakhir, Komponen teman yang tepat akan diinisiasi. Di sana, saya ingin mengambil / mendapatkan daftar teman-teman saya yang disimpan di file friends.json. Sampai sekarang semuanya berfungsi dengan baik. Tapi saya masih pemula untuk layanan HTTP angular2 menggunakan RxJs yang dapat diamati, peta, berlangganan konsep. Saya sudah mencoba memahaminya dan membaca beberapa artikel tetapi sampai saya masuk ke pekerjaan praktis, saya tidak akan memahami konsep-konsep itu dengan benar.

Di sini saya sudah membuat plnkr yang berfungsi kecuali pekerjaan terkait HTTP.

Plnkr

teman saya

 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.

       }
  }

Mohon panduan dan jelaskan dengan benar. Saya tahu ini akan sangat bermanfaat bagi banyak pengembang baru.

Jawaban:


205

Di sinilah Anda salah:

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

harus:

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

atau

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

Anda telah membuat dua kesalahan:

1- Anda menetapkan sendiri yang dapat diamati itu this.result. Ketika Anda benar-benar ingin menetapkan daftar teman this.result. Cara yang benar untuk melakukannya adalah:

  • Anda berlangganan yang diamati. .subscribeadalah fungsi yang sebenarnya mengeksekusi yang diamati. Dibutuhkan tiga parameter panggilan balik sebagai berikut:

    .subscribe(success, failure, complete);

sebagai contoh:

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

Biasanya, Anda mengambil hasil dari callback sukses dan menetapkannya ke variabel Anda. panggilan balik kesalahan cukup jelas. panggilan balik lengkap digunakan untuk menentukan bahwa Anda telah menerima hasil terakhir tanpa kesalahan. Di plunker Anda, panggilan balik lengkap akan selalu dipanggil setelah keberhasilan atau panggilan balik kesalahan.

2- Kesalahan kedua, Anda disebut .json()pada .map(res => res.json()), maka Anda menyebutnya lagi pada callback keberhasilan diamati. .map()adalah transformator yang akan mengubah hasilnya menjadi apa pun yang Anda kembalikan (dalam kasus Anda .json()) sebelum diteruskan ke panggilan balik sukses, Anda harus menyebutnya sekali di salah satu dari mereka.


2
di sini kamu pergi plunker kamu . Saya mengubah baris: 21, 23 di myfriends.ts
Abdulrahman Alsoghayer

1
Apa yang saya tidak mengerti adalah mengapa menggunakan fungsi "peta" di sini? Kita bisa memanggil json pada hasilnya. Jadi apa manfaatnya melakukannya?
rubmz

5
Anda benar @rubmz. Anda bisa melakukan itu seperti yang saya sebutkan dalam jawaban saya. Tetapi, satu manfaat besar adalah memisahkan logika. Misalnya, dalam layanan Anda, Anda memiliki fungsi getFriends(){return http.get('friends.json').map(r => r.json());}. Sekarang, Anda dapat menelepon getFriends().subscribe(...)tanpa harus menelepon .json()setiap saat.
Abdulrahman Alsoghayer

2
Ya, ini hanya sedikit membingungkan bagi pemula. Apa yang dilakukan oleh peta misterious () dan apa yang tidak ... Tapi akhirnya saya mendapatkannya juga :)
rubmz

1
@Abdulrahman, mungkin Anda akan tertarik untuk melihat pertanyaan ini juga: stackoverflow.com/questions/40505691/…
nyluje

138

Konsep

Dapat diobservasi dalam menangani proses dan acara asinkron pendek. Dibandingkan dengan janji, ini dapat digambarkan sebagai acara yang dapat diobservasi = janji + acara.

Apa yang hebat dengan yang bisa diamati adalah bahwa mereka malas, mereka dapat dibatalkan dan Anda dapat menerapkan beberapa operator di dalamnya (seperti map, ...). Ini memungkinkan untuk menangani hal-hal yang tidak sinkron dengan cara yang sangat fleksibel.

Sampel yang hebat menggambarkan kekuatan terbaik yang dapat diobservasi adalah cara untuk menghubungkan input filter ke daftar filter yang sesuai. Ketika pengguna memasukkan karakter, daftar di-refresh. Dapat diamati menangani permintaan AJAX yang sesuai dan membatalkan permintaan dalam proses sebelumnya jika permintaan lain dipicu oleh nilai baru dalam input. Ini kode yang sesuai:

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

(textValue adalah kontrol yang terkait dengan input filter).

Berikut ini adalah deskripsi yang lebih luas dari use case tersebut: Bagaimana cara melihat perubahan bentuk di Angular 2? .

Ada dua presentasi hebat di AngularConnect 2015 dan EggHead:

Christoph Burgdorf juga menulis beberapa posting blog yang bagus tentang masalah ini:

Beraksi

Sebenarnya mengenai kode Anda, Anda mencampur dua pendekatan ;-) Inilah mereka:

  • Kelola yang bisa diamati dengan Anda sendiri . Dalam hal ini, Anda bertanggung jawab untuk memanggil subscribemetode pada yang dapat diamati dan menetapkan hasilnya ke dalam atribut komponen. Anda kemudian dapat menggunakan atribut ini dalam tampilan untuk beralih ke koleksi:

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

    Pengembalian dari keduanya getdan mapmetode yang diamati bukan hasilnya (dengan cara yang sama daripada dengan janji).

  • Biarkan mengelola yang dapat diamati dengan templat Angular . Anda juga dapat memanfaatkan asyncpipa untuk mengelola secara implisit pengamatan. Dalam hal ini, tidak perlu memanggil subscribemetode secara eksplisit .

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

Anda dapat melihat bahwa yang diamati itu malas. Jadi permintaan HTTP yang sesuai hanya akan dipanggil sekali pendengar dengan melampirkan di atasnya menggunakansubscribe metode.

Anda juga dapat melihat bahwa mapmetode ini digunakan untuk mengekstraksi konten JSON dari respons dan menggunakannya kemudian dalam pemrosesan yang dapat diamati.

Semoga ini bisa membantu Anda, Thierry


Terima kasih untuk semua referensi. Tetapi bisakah Anda membantu saya dengan celana saya?
nyks

Saya memperbarui jawaban saya dengan lebih detail mengenai kode Anda. Semoga ini akan membantu Anda ;-)
Thierry Templier

maaf saya tidak bisa menerima jawaban Anda. Itu lebih jelas tetapi jawaban yang diterima dan dihargai membantu saya cukup memahami tentang pertanyaan saya. Tapi mudah-mudahan Anda akan mendapatkan hit yang baik untuk jawaban yang jelas karena Anda memiliki penjelasan yang lebih rinci. Jawaban yang diterima juga untuk mengecilkan dasar yang baik.
micronyks

2
Thierry Templier ini adalah jawaban yang sangat baik tetapi satu hal yang tidak jelas bagi saya, saya pikir http.get ('friends.json') .map (response => response.json ()) mengembalikan yang dapat diamati <Array <Object>>. Jika ya, mengapa Anda mengirimnya ke sini. mereka adalah tipe yang berbeda.
Stav Alfi

@StavAlfi pipesjuga merupakan observables. lihat video ini: youtube.com/watch?v=bVI5gGTEQ_U disarankan oleh thierry untuk info lebih lanjut.
jujur

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

API HttpClient diperkenalkan di versi 4.3.0. Ini adalah evolusi dari API HTTP yang ada dan memiliki paket sendiri @ angular / common / http. Salah satu perubahan yang paling penting adalah bahwa sekarang objek respons adalah JSON secara default, jadi tidak perlu menguraikannya dengan metode peta lagi. Jauh bisa kita gunakan seperti di bawah ini

http.get('friends.json').subscribe(result => this.result =result);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.