HTTP GET angolare con errore TypeScript http.get (…) .map non è una funzione in [null]


334

Ho un problema con HTTP in angolare.

Voglio solo GETun JSONelenco e mostrarlo nella vista.

Classe di servizio

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

E nel HallListComponentchiamo il getHallsmetodo dal servizio:

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

Tuttavia, ho ottenuto un'eccezione:

TypeError: this.http.get (...). Map non è una funzione in [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{}

app.component

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"
  ]
}

Http.get non restituisce una promessa?
bmm6o

1
@ bmm6o Il nuovo Httpservizio restituisce un osservabile
Brocco

1
Ho riscontrato un problema quasi identico, cercando di migrare un progetto da Angular2 beta-17 alla versione finale. Il problema per me era il mio IDE, tuttavia, usando VS 2015, Aggiornamento 3. L'estensione del servizio di linguaggio TypeScript era ancora disponibile 1.8.36, mentre la guida di avvio rapido ng2 (mentre scrivo questo) sta usando "typescript": "^2.0.2". Aggiornamento del lang TS. il servizio tramite estensioni e aggiornamenti mi ha aiutato. Durante l'installazione dell'aggiornamento mi sono imbattuto in questa risposta SO , che termina con la stessa conclusione.
Eric Lease,

Per phpstorm / webstorm, anche l'aggiornamento della versione dattiloscritta con la libreria del mio progetto ha risolto il problema. Ho seguito i passaggi di questa risposta SO: stackoverflow.com/a/31608934/1291428
Sebas

Risposte:


538

Penso che sia necessario importare questo:

import 'rxjs/add/operator/map'

O più in generale questo se vuoi avere più metodi per osservabili. ATTENZIONE: Questo importerà tutti gli oltre 50 operatori e li aggiungerà all'applicazione, influendo così sulla dimensione del pacchetto e sui tempi di caricamento.

import 'rxjs/Rx';

Vedi questo numero per maggiori dettagli.


1
Quali errori rimangono ancora? Puoi fare alcune domande specifiche al riguardo su stackoverflow ;-) Questa domanda potrebbe forse aiutarti anche: stackoverflow.com/questions/34450131/… .
Thierry Templier,

1
A partire da Angular 2 RC 0, questo non è più necessario.
Onur Yıldırım,

3
@ OnurYıldırım, usando rc.4, questa importazione è ancora necessaria, a meno che non stia facendo qualcosa di sbagliato.
Joseph Gabriel,

18
Per favore non usare 'import' rxjs / Rx ';' perché importa tutto e rxjs tende ad essere piuttosto grande. Importa gli operatori uno per uno quando ne hai bisogno.
Trascina 0

1
Angolare 2 con rxjs: 5.0.0-beta.12 qui. E dovevo ancora import 'rxjs/add/operator/do'... Mentre non dobbiamo più farlo per .map(). Ma questo ha aiutato il mio .do()caso, a rendermi conto che devo specificatamente importarlo. Grazie! Un voto
positivo

82

Solo alcuni retroscena ... La guida per sviluppatori di comunicazione server recentemente coniata (finalmente) discute / menziona / spiega questo:

La libreria RxJS è piuttosto grande. Le dimensioni contano quando creiamo un'applicazione di produzione e la distribuiamo su dispositivi mobili. Dovremmo includere solo quelle funzionalità di cui abbiamo effettivamente bisogno.

Di conseguenza, Angular espone una versione ridotta Observablenel rxjs/Observablemodulo, una versione che manca di quasi tutti gli operatori, compresi quelli che vorremmo usare qui come il mapmetodo.

Sta a noi aggiungere gli operatori di cui abbiamo bisogno. Potremmo aggiungere ciascun operatore, uno per uno, fino a quando un'implementazione osservabile personalizzata sarà sintonizzata esattamente sulle nostre esigenze.

Quindi, come ha già risposto @Thierry, possiamo semplicemente inserire gli operatori di cui abbiamo bisogno:

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

Oppure, se siamo pigri, possiamo inserire l'intera serie di operatori. ATTENZIONE: questo aggiungerà tutti gli oltre 50 operatori al pacchetto dell'app e influirà sui tempi di caricamento

import 'rxjs/Rx';

2
import 'rxjs / Rx'; Wow. e tutti i miei capelli che tirano immediatamente scompaiono. non posso credere che questo non sia stampato in tutto il mondo per Rxjs / Angular2. Grazie!!!
JimB,

Ma spesso non sfilaccia, per impostazione predefinita è un'importazione nella lista nera. Crea un nuovo progetto CLI angolare, vedrai. Adoro la comodità, ma la convention nei luoghi in cui lavoro a New York non è di farlo.
Tim Consolazio,

21

Da rxjs 5.5 in poi, è possibile utilizzare gli operatori pipable

import { map } from 'rxjs/operators';

Cosa c'è che non va nel import 'rxjs/add/operator/map';

Quando utilizziamo questo approccio, l' mapoperatore verrà corretto observable.prototype e diventerà parte di questo oggetto.

Se in seguito, decidi di rimuovere l' mapoperatore dal codice che gestisce il flusso osservabile ma non riesci a rimuovere la corrispondente dichiarazione di importazione, il codice che implementa maprimane parte del Observable.prototype.

Quando i bundler cercano di eliminare il codice inutilizzato ( aka tree shaking ), possono decidere di mantenere il codice mapdell'operatore nell'Osservabile anche se non viene utilizzato nell'applicazione.

Soluzione -Pipeable operators

Gli operatori pipable sono funzioni pure e non patch l' Osservabile . È possibile importare operatori utilizzando la sintassi di importazione ES6 import { map } from "rxjs/operators"e quindi inserirli in una funzione pipe()che accetta un numero variabile di parametri, ovvero operatori concatenabili.

Qualcosa come questo:

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

16

Con Angular 5 l'importazione di RxJS è migliorata.

Invece di

import 'rxjs/add/operator/map';

Ora possiamo

import { map } from 'rxjs/operators';

Usando questo approccio, ora nella tua build includerà solo operatori usati (mappa in questo caso), in precedenza includeva tutti gli operatori della libreria rxjs. controlla sotto il link per maggiori dettagli. loiane.com/2017/08/angular-rxjs-imports
Hiren Shah,

13

L'uso Observable.subscribediretto dovrebbe funzionare.

@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
Questo non è un approccio molto efficiente. Ad esempio, se ci sono più abbonati, ciascuno dovrà eseguire la mappa sui dati, invece di farlo solo una volta nel servizio. Penso che OP avesse l'approccio giusto, ma non aveva il modulo giusto caricato per usarlo.
Evan Plaice,

3

Per le versioni angolari 5 e successive, la riga di importazione aggiornata è simile a:

import { map } from 'rxjs/operators';

O

import { map } from 'rxjs/operators';

Inoltre, queste versioni supportano totalmente gli operatori Pipable in modo da poter usare facilmente .pipe () e .subscribe ().

Se si utilizza Angular versione 2, la seguente riga dovrebbe funzionare perfettamente:

import 'rxjs/add/operator/map';

O

import 'rxjs/add/operators/map';

Se il problema persiste, devi procedere con:

import 'rxjs/Rx';

Non preferirò che tu lo usi direttamente perché aumenta il tempo di caricamento, poiché ha un gran numero di operatori (utili e non utili) che non è una buona pratica secondo le norme del settore, quindi assicurati si tenta di utilizzare prima le righe di importazione sopra menzionate e, se ciò non funziona, si dovrebbe scegliere rxjs / Rx


3

Ho una soluzione a questo problema

Installa questo pacchetto:

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

quindi importare questa libreria

import 'rxjs/add/operator/map'

finalmente riavvia il tuo progetto ionico allora

ionic serve -l

3

Versione angolare 6 "0.6.8" versione rxjs 6 "^ 6.0.0"

questa soluzione è per:

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

come tutti sappiamo, angular viene sviluppato ogni giorno, quindi ogni giorno ci sono molti cambiamenti e questa soluzione è per angular 6 e rxjs 6 per la
prima volta su cui lavorare con http da cui è necessario importarlo: dopotutto devi dichiarare l'HttpModule in app. module.ts

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

e devi aggiungere HttpModule a Ngmodule -> importazioni

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

secondo per lavorare con la mappa dovresti prima importare pipe:

import { pipe } from 'rxjs';

in terzo luogo è necessario importare la funzione mappa da:

import { map } from 'rxjs/operators';

devi usare map inside pipe come questo esempio:

 constructor(public http:Http){  }

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

che funziona perfettamente buona fortuna!


2

La mappa che stai usando qui, non è .map()in javascript, è la funzione della mappa Rxjs su cui sta lavorandoObservables in Angolare ...

Quindi in tal caso è necessario importarlo se si desidera utilizzare la mappa sui dati dei risultati ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Applica una determinata funzione di progetto a ciascun valore emesso dall'osservabile di origine ed emette i valori risultanti come osservabile.

Quindi semplicemente importalo in questo modo:

import 'rxjs/add/operator/map';

1

Poiché il servizio Http in angular2 restituisce un tipo Osservabile , dalla directory di installazione di Angular2 ('node_modules' nel mio caso), abbiamo bisogno di importare la funzione cartografica dell'Osservabile nel tuo componente usando il servizio http , come:

import 'rxjs/add/operator/map';


1

Aggiungi la linea nel tuo file,

import 'rxjs / Rx';

Importerà un mucchio di dipendenze. Testato nell'angolo 5


0

È vero, RxJs ha separato il suo operatore di mappa in un modulo separato e ora è necessario importarlo esplicitamente come qualsiasi altro operatore.

import rxjs/add/operator/map;

e starai bene.


0

L'importazione globale è sicura.

import 'rxjs / Rx';


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

risolverà il tuo problema

L'ho provato in angolare 5.2.0 e rxjs 5.5.2


0

questo accade perché stai usando rxjs e nella funzione rxjs non sono statici, il che significa che non puoi chiamarli direttamente devi chiamare i metodi all'interno della pipe e importare quella funzione dalla libreria rxjs

Ma se stai usando rxjs-compat, devi solo importare gli operatori rxjs-compat


0

Ho provato sotto i comandi e viene risolto:

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


import 'rxjs/Rx';

Questo è solo per farti inizialmente lavorare in rxjs 6 eseguendo alcune patch per te. È solo una soluzione a breve termine e dovrebbe essere effettuata la transizione completa di rxjs 6.
HankCa,

0

importare {map} da 'rxjs / operatori';

questo funziona per me in 8 angolare


0

Oltre a ciò che ha commentato @ mlc-mlapis, si stanno mescolando operatori consentiti e il metodo di patching del prototipo. Usa l'uno o l'altro .

Per il tuo caso dovrebbe essere

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.