HTTP GET Angular dengan kesalahan TypeScript http.get (...) .map bukan fungsi di [null]


334

Saya punya masalah dengan HTTP di Angular.

Aku hanya ingin GETsebuah JSONdaftar dan menunjukkan dalam pandangan.

Kelas layanan

import {Injectable} from "angular2/core";
import {Hall} from "./hall";
import {Http} from "angular2/http";
@Injectable()
export class HallService {
    public http:Http;
    public static PATH:string = 'app/backend/'    

    constructor(http:Http) {
        this.http=http;
    }

    getHalls() {
           return this.http.get(HallService.PATH + 'hall.json').map((res:Response) => res.json());
    }
}

Dan di HallListComponentsaya memanggil getHallsmetode dari layanan:

export class HallListComponent implements OnInit {
    public halls:Hall[];
    public _selectedId:number;

    constructor(private _router:Router,
                private _routeParams:RouteParams,
                private _service:HallService) {
        this._selectedId = +_routeParams.get('id');
    }

    ngOnInit() {
        this._service.getHalls().subscribe((halls:Hall[])=>{ 
            this.halls=halls;
        });
    }
}

Namun, saya mendapat pengecualian:

TypeError: this.http.get (...). Map bukan fungsi di [null]

hall-center.component

import {Component} from "angular2/core";
import {RouterOutlet} from "angular2/router";
import {HallService} from "./hall.service";
import {RouteConfig} from "angular2/router";
import {HallListComponent} from "./hall-list.component";
import {HallDetailComponent} from "./hall-detail.component";
@Component({
    template:`
        <h2>my app</h2>
        <router-outlet></router-outlet>
    `,
    directives: [RouterOutlet],
    providers: [HallService]
})

@RouteConfig([
    {path: '/',         name: 'HallCenter', component:HallListComponent, useAsDefault:true},
    {path: '/hall-list', name: 'HallList', component:HallListComponent}
])

export class HallCenterComponent{}

komponen aplikasi

import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
import {RouteConfig} from "angular2/router";
import {HallCenterComponent} from "./hall/hall-center.component";
@Component({
    selector: 'my-app',
    template: `
        <h1>Examenopdracht Factory</h1>
        <a [routerLink]="['HallCenter']">Hall overview</a>
        <router-outlet></router-outlet>
    `,
    directives: [ROUTER_DIRECTIVES]
})

@RouteConfig([
    {path: '/hall-center/...', name:'HallCenter',component:HallCenterComponent,useAsDefault:true}
])
export class AppComponent { }

tsconfig.json

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}

Tidakkah http.get mengembalikan janji?
bmm6o

1
@ bmm6o Layanan baru Httpmengembalikan yang dapat diamati
Brocco

1
Saya mengalami masalah yang hampir sama, mencoba untuk bermigrasi proyek dari Angular2 beta-17 ke rilis final. Masalahnya bagi saya adalah IDE saya, menggunakan VS 2015, Pembaruan 3. Ekstensi layanan bahasa TypeScript masih di 1.8.36, sedangkan sebagai panduan quickstart ng2 (saat saya menulis ini) menggunakan "typescript": "^2.0.2". Meningkatkan TS lang. layanan melalui Ekstensi dan Pembaruan melakukan trik untuk saya. Sementara pembaruan itu sedang diinstal, saya menemukan jawaban SO ini , yang berakhir dengan kesimpulan yang sama.
Eric Lease

Untuk phpstorm / webstorm, memperbarui versi naskah dengan perpustakaan proyek saya juga memecahkan masalah. Saya mengikuti langkah-langkah jawaban SO ini: stackoverflow.com/a/31608934/1291428
Sebas

Jawaban:


538

Saya pikir Anda perlu mengimpor ini:

import 'rxjs/add/operator/map'

Atau lebih umum ini jika Anda ingin memiliki lebih banyak metode untuk diamati. PERINGATAN: Ini akan mengimpor semua 50+ operator dan menambahkannya ke aplikasi Anda, sehingga memengaruhi ukuran bundel dan waktu muat Anda.

import 'rxjs/Rx';

Lihat masalah ini untuk lebih jelasnya.


1
Kesalahan mana yang masih tersisa? Anda dapat mengajukan beberapa pertanyaan spesifik mengenai hal ini di stackoverflow ;-) Pertanyaan ini mungkin bisa membantu Anda juga: stackoverflow.com/questions/34450131/… .
Thierry Templier

1
Pada Angular 2 RC 0, ini tidak lagi diperlukan.
Onur Yıldırım

3
@ OnurYıldırım, menggunakan rc.4, impor ini masih diperlukan, kecuali saya melakukan sesuatu yang salah.
Joseph Gabriel

18
Harap jangan gunakan 'import' rxjs / Rx ';' karena mengimpor semuanya dan rxj cenderung cukup besar. Impor operator satu per satu sesuai kebutuhan Anda.
Tarik0

1
Sudut 2 dengan rxjs: 5.0.0-beta.12 di sini. Dan saya masih harus import 'rxjs/add/operator/do'... Meskipun kita tidak perlu melakukan ini .map()lagi. Tetapi ini membantu .do()kasus saya , untuk menyadari bahwa saya secara khusus perlu mengimpornya. Terima kasih! Satu suara dari saya :)
MrCroft

82

Hanya beberapa latar belakang ... Panduan pengembang Server Communication yang baru dicetak (akhirnya) membahas / menyebutkan / menjelaskan ini:

Perpustakaan RxJS cukup besar. Ukuran penting ketika kita membangun aplikasi produksi dan menyebarkannya ke perangkat seluler. Kita harus memasukkan hanya fitur-fitur yang sebenarnya kita butuhkan.

Karenanya, Angular memaparkan versi stripped down Observabledalam rxjs/Observablemodul, versi yang tidak memiliki hampir semua operator termasuk yang ingin kami gunakan di sini seperti mapmetode.

Terserah kita untuk menambahkan operator yang kita butuhkan. Kami dapat menambahkan masing-masing operator, satu per satu, hingga kami memiliki implementasi kustom yang dapat diamati, yang disesuaikan dengan kebutuhan kami.

Jadi karena @Thierry sudah menjawab, kita bisa menarik operator yang kita butuhkan:

import 'rxjs/add/operator/map';
import 'rxjs/operator/delay';
import 'rxjs/operator/mergeMap';
import 'rxjs/operator/switchMap';

Atau, jika kita malas kita dapat menarik set lengkap operator. PERINGATAN: ini akan menambahkan semua 50+ operator ke bundel aplikasi Anda, dan akan memengaruhi waktu muat

import 'rxjs/Rx';

2
impor 'rxjs / Rx'; Wow. dan semua rambutku yang menarik segera hilang. Saya tidak percaya ini tidak dicetak di seluruh dunia untuk Rxjs / Angular2. Terima kasih!!!
JimB

Tapi itu sering tidak akan lint, secara default itu adalah impor daftar hitam. Buat proyek CLI sudut baru, Anda akan melihat. Saya suka kenyamanan itu sendiri tetapi kebaktian di tempat saya bekerja di NYC bukanlah untuk melakukannya.
Tim Consolazio

21

Dari rxjs 5.5 dan seterusnya, Anda dapat menggunakan operator pipabel

import { map } from 'rxjs/operators';

Apa yang salah dengan import 'rxjs/add/operator/map';

Ketika kita menggunakan mapoperator pendekatan ini akan ditambal ke observable.prototype dan menjadi bagian dari objek ini.

Jika nanti, Anda memutuskan untuk menghapus mapoperator dari kode yang menangani aliran yang dapat diamati tetapi gagal menghapus pernyataan impor yang sesuai, kode yang mengimplementasikannya maptetap menjadi bagian dari Observable.prototype.

Ketika bundler mencoba menghilangkan kode yang tidak digunakan ( alias tree shaking ), mereka dapat memutuskan untuk menyimpan kode mapoperator di Observable meskipun itu tidak digunakan dalam aplikasi.

Solusi -Pipeable operators

Operator pipa adalah fungsi murni dan tidak menambal Yang Dapat Diamati . Anda dapat mengimpor operator menggunakan sintaks impor ES6 import { map } from "rxjs/operators"dan kemudian membungkusnya ke dalam fungsi pipe()yang mengambil sejumlah variabel parameter, yaitu operator yang dapat dihubungkan.

Sesuatu seperti ini:

getHalls() {
    return this.http.get(HallService.PATH + 'hall.json')
    .pipe(
        map((res: Response) => res.json())
    );
}

16

Dengan Angular 5 impor RxJS ditingkatkan.

Dari pada

import 'rxjs/add/operator/map';

Kita sekarang bisa

import { map } from 'rxjs/operators';

Menggunakan pendekatan ini, sekarang di build Anda hanya akan menyertakan operator yang digunakan (peta dalam hal ini), sebelumnya itu termasuk semua operator dari perpustakaan rxjs. periksa tautan di bawah untuk detail lebih lanjut. loiane.com/2017/08/angular-rxjs-import
Hiren Shah

13

Penggunaan Observable.subscribesecara langsung seharusnya berhasil.

@Injectable()
export class HallService {
    public http:Http;
    public static PATH:string = 'app/backend/'    

    constructor(http:Http) {
        this.http=http;
    }

    getHalls() {
    // ########### No map
           return this.http.get(HallService.PATH + 'hall.json');
    }
}


export class HallListComponent implements OnInit {
    public halls:Hall[];
    / *** /
    ngOnInit() {
        this._service.getHalls()
           .subscribe(halls => this.halls = halls.json()); // <<--
    }
}

5
Ini bukan pendekatan yang sangat efisien. Misalnya jika ada beberapa pelanggan, mereka masing-masing harus menjalankan peta pada data, daripada hanya melakukannya sekali dalam layanan. Saya pikir OP memiliki pendekatan yang tepat, hanya saja modul yang dimuat tidak tepat untuk menggunakannya.
Evan Plaice

3

Untuk versi Angular 5 ke atas, garis impor yang diperbarui terlihat seperti:

import { map } from 'rxjs/operators';

ATAU

import { map } from 'rxjs/operators';

Juga versi ini benar-benar mendukung Pipable Operator sehingga Anda dapat dengan mudah menggunakan .pipe () dan .scribe ().

Jika Anda menggunakan Angular versi 2, maka baris berikut akan berfungsi dengan baik:

import 'rxjs/add/operator/map';

ATAU

import 'rxjs/add/operators/map';

Jika Anda masih mengalami masalah maka Anda harus pergi dengan:

import 'rxjs/Rx';

Saya tidak akan memilih Anda untuk menggunakannya secara langsung karena akan meningkatkan waktu pemuatan, karena memiliki banyak operator di dalamnya (yang berguna dan yang tidak berguna) yang bukan praktik yang baik sesuai dengan norma industri, jadi pastikan Anda mencoba menggunakan jalur impor yang disebutkan di atas terlebih dahulu, dan jika itu tidak berhasil, Anda harus menggunakan rxjs / Rx


3

Saya punya solusi untuk masalah ini

Instal paket ini:

npm install rxjs@6 rxjs-compat@6 --save

lalu impor perpustakaan ini

import 'rxjs/add/operator/map'

akhirnya restart proyek ion Anda

ionic serve -l

3

Versi sudut 6 "0.6.8" rxjs versi 6 "^ 6.0.0"

solusi ini untuk:

  "@angular-devkit/core": "0.6.8",
  "rxjs": "^6.0.0"

seperti yang kita semua tahu sudut sedang dikembangkan setiap hari sehingga ada banyak perubahan setiap hari dan solusi ini adalah untuk sudut 6 dan rxjs 6
pertama untuk bekerja dengan http yo Anda harus mengimpornya dari: setelah semua Anda harus mendeklarasikan HttpModule dalam aplikasi. module.ts

import { Http } from '@angular/http';

dan Anda harus menambahkan HttpModule ke Ngmodule -> impor

  imports: [
    HttpModule,
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(appRoutes)
  ],

kedua untuk bekerja dengan peta, Anda harus terlebih dahulu mengimpor pipa:

import { pipe } from 'rxjs';

ketiga Anda memerlukan fungsi peta impor dari:

import { map } from 'rxjs/operators';

Anda harus menggunakan peta di dalam pipa seperti contoh ini:

 constructor(public http:Http){  }

    getusersGET(){
        return this.http.get('http://jsonplaceholder.typicode.com/users').pipe(
         map(res => res.json()  )  );
    }

itu berhasil, semoga berhasil!


2

The Peta Anda gunakan di sini, bukan .map()di javascript, itu fungsi peta Rxjs yang bekerja di Observablesdi sudut ...

Jadi dalam hal ini Anda perlu mengimpornya jika Anda ingin menggunakan peta pada data hasil ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Menerapkan fungsi proyek yang diberikan untuk setiap nilai yang dipancarkan oleh sumber yang Dapat Diobservasi, dan memancarkan nilai yang dihasilkan sebagai Yang Dapat Diamati.

Jadi cukup impor seperti ini:

import 'rxjs/add/operator/map';

1

Karena layanan Http di angular2 mengembalikan jenis yang Dapat Diobservasi , Dari direktori instalasi Angular2 Anda ('node_modules' dalam kasus saya), Kami perlu mengimpor fungsi peta yang Dapat Diamati dalam komponen Anda menggunakan layanan http , seperti:

import 'rxjs/add/operator/map';


1

Cukup tambahkan baris dalam file Anda,

impor 'rxjs / Rx';

Ini akan mengimpor banyak dependensi. Diuji dalam sudut 5


0

Benar, RxJ telah memisahkan operator petanya dalam modul yang terpisah dan sekarang Anda perlu mengimpornya secara eksplisit seperti operator lainnya.

import rxjs/add/operator/map;

dan kamu akan baik-baik saja.



0
import 'rxjs/add/operator/map';

akan menyelesaikan masalah Anda

Saya mengujinya dalam angular 5.2.0 dan rxjs 5.5.2


0

ini terjadi karena Anda menggunakan fungsi rxjs dan rxjs tidak statis yang berarti Anda tidak dapat memanggil mereka secara langsung, Anda harus memanggil metode di dalam pipa dan mengimpor fungsi itu dari perpustakaan rxjs

Tetapi jika Anda menggunakan rxjs-compat maka Anda hanya perlu mengimpor operator rxjs-compat


0

Saya mencoba perintah di bawah ini dan diperbaiki:

npm install rxjs@6 rxjs-compat@6 --save


import 'rxjs/Rx';

Itu hanya untuk membuat Anda awalnya bekerja di rxjs 6 dengan melakukan beberapa perbaikan untuk Anda. Ini hanya perbaikan jangka pendek dan transisi rxjs 6 penuh harus dilakukan.
HankCa


0

Ditambah apa yang dikomentari @ mlc-mlapis, Anda mencampurkan operator yang dapat diterima dan metode penambalan prototipe. Gunakan satu atau yang lain .

Untuk kasus Anda seharusnya

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';

@Injectable()
export class SwPeopleService {
    people$ = this.http.get('https://swapi.co/api/people/')
      .map((res:any) => res.results);

    constructor(private http: HttpClient) {} 
}

https://stackblitz.com/edit/angular-http-observables-9nchvz?file=app%2Fsw-people.service.ts

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.