HTTP GET angulaire avec erreur TypeScript http.get (…) .map n'est pas une fonction dans [null]


334

J'ai un problème avec HTTP dans Angular.

Je veux juste GETune JSONliste et la montrer dans la vue.

Classe de service

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

Et dans le HallListComponentj'appelle la getHallsméthode du service:

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

Cependant, j'ai eu une exception:

TypeError: this.http.get (...). Map n'est pas une fonction dans [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 ne renvoie-t-il pas une promesse?
bmm6o

1
@ bmm6o Le nouveau Httpservice retourne un observable
Brocco

1
J'ai rencontré un problème presque identique, essayant de migrer un projet d'Angular2 beta-17 vers la version finale. Le problème pour moi était mon IDE cependant, en utilisant VS 2015, mise à jour 3. L'extension du service de langage TypeScript était toujours là 1.8.36, alors que le guide de démarrage rapide ng2 (au moment où j'écris ceci) utilise "typescript": "^2.0.2". Mise à niveau du TS lang. le service via les extensions et les mises à jour a fait l'affaire pour moi. Pendant l'installation de cette mise à jour, je suis tombé sur cette réponse SO , qui se termine par la même conclusion.
Eric Lease

Pour phpstorm / webstorm, la mise à jour de la version dactylographiée avec la bibliothèque de mon projet a également résolu le problème. J'ai suivi les étapes de cette réponse SO: stackoverflow.com/a/31608934/1291428
Sebas

Réponses:


538

Je pense que vous devez importer ceci:

import 'rxjs/add/operator/map'

Ou plus généralement ceci si vous voulez avoir plus de méthodes pour les observables. AVERTISSEMENT: cela importera tous les 50+ opérateurs et les ajoutera à votre application, affectant ainsi la taille de votre bundle et les temps de chargement.

import 'rxjs/Rx';

Consultez ce numéro pour plus de détails.


1
Quelles erreurs subsistent encore? Vous pouvez poser des questions spécifiques à ce sujet sur stackoverflow ;-) Cette question pourrait peut-être aussi vous aider: stackoverflow.com/questions/34450131/… .
Thierry Templier

1
Depuis Angular 2 RC 0, cela n'est plus nécessaire.
Onur Yıldırım

3
@ OnurYıldırım, en utilisant rc.4, cette importation est toujours requise, sauf si je fais quelque chose de mal.
Joseph Gabriel

18
Veuillez ne pas utiliser 'import' rxjs / Rx ';' car il importe tout et rxjs a tendance à être assez gros. Importez les opérateurs un par un selon vos besoins.
Drag0

1
Angular 2 avec rxjs: 5.0.0-beta.12 ici. Et je devais encore import 'rxjs/add/operator/do'... Bien que nous n'ayons plus besoin de faire ça .map(). Mais cela a aidé mon .do()cas, à réaliser que je dois spécifiquement l'importer. Je vous remercie! Un vote
positif

82

Juste un peu d'histoire ... Le tout nouveau guide de développement Server Communication (enfin) discute / mentionne / explique ceci:

La bibliothèque RxJS est assez grande. La taille est importante lorsque nous créons une application de production et la déployons sur des appareils mobiles. Nous ne devons inclure que les fonctionnalités dont nous avons réellement besoin.

En conséquence, Angular expose une version allégée de Observabledans le rxjs/Observablemodule, une version qui manque de presque tous les opérateurs, y compris ceux que nous aimerions utiliser ici, comme la mapméthode.

A nous d'ajouter les opérateurs dont nous avons besoin. Nous pourrions ajouter chaque opérateur, un par un, jusqu'à ce que nous ayons une implémentation Observable personnalisée adaptée précisément à nos besoins.

Donc, comme @Thierry a déjà répondu, nous pouvons simplement attirer les opérateurs dont nous avons besoin:

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

Ou, si nous sommes paresseux, nous pouvons tirer l'ensemble complet des opérateurs. AVERTISSEMENT: cela ajoutera tous les 50+ opérateurs à votre ensemble d'applications et affectera les temps de chargement

import 'rxjs/Rx';

2
importer 'rxjs / Rx'; sensationnel. et tous mes cheveux tirant disparaissent instantanément. je ne peux pas croire que ce n'est pas imprimé partout dans le monde pour Rxjs / Angular2. Merci!!!
JimB

Mais souvent, il ne peluche pas, par défaut, c'est une importation sur liste noire. Créez un nouveau projet CLI angulaire, vous verrez. J'aime moi-même la commodité, mais la convention dans les endroits où je travaille à New York n'est pas de le faire.
Tim Consolazio

21

À partir de rxjs 5.5 , vous pouvez utiliser les opérateurs canalisables

import { map } from 'rxjs/operators';

Quel est le problème avec le import 'rxjs/add/operator/map';

Lorsque nous utilisons cette approche, l' mapopérateur est corrigé observable.prototype et devient une partie de cet objet.

Si plus tard, vous décidez de supprimer l' mapopérateur du code qui gère le flux observable mais ne supprimez pas l'instruction d'importation correspondante, le code qui implémente mapreste une partie de la Observable.prototype.

Lorsque les bundlers tentent d'éliminer le code inutilisé ( aka tree shaking ), ils peuvent décider de conserver le code du map opérateur dans l'Observable même s'il n'est pas utilisé dans l'application.

Solution -Pipeable operators

Les opérateurs canalisables sont de simples fonctions et ne corrigent pas l' Observable . Vous pouvez importer des opérateurs à l'aide de la syntaxe d'importation ES6 import { map } from "rxjs/operators", puis les encapsuler dans une fonction pipe()qui prend un nombre variable de paramètres, c'est-à-dire des opérateurs chaînables.

Quelque chose comme ça:

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

16

Avec Angular 5, l'importation RxJS est améliorée.

Au lieu de

import 'rxjs/add/operator/map';

Nous pouvons maintenant

import { map } from 'rxjs/operators';

En utilisant cette approche, maintenant dans votre build, il n'inclura que les opérateurs utilisés (carte dans ce cas), auparavant il incluait tous les opérateurs de la bibliothèque rxjs. vérifier le lien ci-dessous pour plus de détails. loiane.com/2017/08/angular-rxjs-imports
Hiren Shah

13

L'utilisation Observable.subscribedirecte devrait fonctionner.

@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
Ce n'est pas une approche très efficace. Par exemple, s'il y a plusieurs abonnés, ils devront chacun exécuter la carte sur les données, plutôt que de le faire une seule fois dans le service. Je pense que OP avait la bonne approche, n'avait tout simplement pas le bon module chargé pour l'utiliser.
Evan Plaice

3

Pour les versions angulaires 5 et supérieures, la ligne d'importation mise à jour ressemble à:

import { map } from 'rxjs/operators';

OU

import { map } from 'rxjs/operators';

De plus, ces versions prennent totalement en charge les opérateurs pipables afin que vous puissiez facilement utiliser .pipe () et .subscribe ().

Si vous utilisez la version angulaire 2, la ligne suivante devrait fonctionner parfaitement:

import 'rxjs/add/operator/map';

OU

import 'rxjs/add/operators/map';

Si vous rencontrez toujours un problème, vous devez choisir:

import 'rxjs/Rx';

Je ne préférerais pas que vous l'utilisiez directement car il augmente le temps de chargement, car il contient un grand nombre d'opérateurs (utiles et inutiles), ce qui n'est pas une bonne pratique selon les normes de l'industrie, alors assurez-vous vous essayez d'abord d'utiliser les lignes d'importation mentionnées ci-dessus, et si cela ne fonctionne pas, vous devriez opter pour rxjs / Rx


3

J'ai une solution à ce problème

Installez ce package:

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

puis importez cette bibliothèque

import 'rxjs/add/operator/map'

redémarrez enfin votre projet ionique puis

ionic serve -l

3

Version angulaire 6 "0.6.8" rxjs version 6 "^ 6.0.0"

cette solution est pour:

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

comme nous le savons tous, angular est développé tous les jours, donc il y a beaucoup de changements chaque jour et cette solution est pour angular 6 et rxjs 6 d'
abord pour travailler avec http, vous devez l'importer: après tout, vous devez déclarer le HttpModule dans l'application. module.ts

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

et vous devez ajouter HttpModule à Ngmodule -> importations

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

deuxième pour travailler avec la carte, vous devez d'abord importer le tuyau:

import { pipe } from 'rxjs';

Troisièmement, vous devez importer la fonction de carte à partir de:

import { map } from 'rxjs/operators';

vous devez utiliser map inside pipe comme cet exemple:

 constructor(public http:Http){  }

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

ça marche parfaitement bonne chance!


2

La carte que vous utilisez ici, n'est pas .map()en javascript, c'est la fonction de carte Rxjs qui fonctionne sur ObservablesAngular ...

Donc, dans ce cas, vous devez l'importer si vous souhaitez utiliser la carte sur les données de résultat ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Applique une fonction de projet donnée à chaque valeur émise par l'observable source et émet les valeurs résultantes en tant qu'observable.

Il suffit donc de l'importer comme ceci:

import 'rxjs/add/operator/map';

1

Étant donné que le service Http dans angular2 renvoie un type Observable , à partir de votre répertoire d'installation Angular2 ('node_modules' dans mon cas), nous devons importer la fonction de carte de l'Observable dans votre composant en utilisant le service http , comme:

import 'rxjs/add/operator/map';


1

Ajoutez simplement la ligne dans votre fichier,

importer 'rxjs / Rx';

Il importera un tas de dépendances.Testé en angulaire 5


0

Certes, RxJs a séparé son opérateur de carte dans un module séparé et vous devez maintenant l'impliquer explicitement comme n'importe quel autre opérateur.

import rxjs/add/operator/map;

et tout ira bien.



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

va résoudre votre problème

Je l'ai testé dans angular 5.2.0 et rxjs 5.5.2


0

cela se produit parce que vous utilisez les rxjs et que la fonction dans rxjs n'est pas statique, ce qui signifie que vous ne pouvez pas les appeler directement, vous devez appeler les méthodes à l'intérieur du canal et importer cette fonction depuis la bibliothèque rxjs

Mais si vous utilisez rxjs-compat, il vous suffit d'importer les opérateurs rxjs-compat


0

J'ai essayé les commandes ci-dessous et cela se corrige:

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


import 'rxjs/Rx';

C'est seulement pour vous permettre de travailler initialement dans rxjs 6 en effectuant quelques correctifs pour vous. Ce n'est qu'un correctif à court terme et la transition complète de rxjs 6 doit être effectuée.
HankCa

0

importer {map} depuis 'rxjs / operators';

cela fonctionne pour moi en angulaire 8


0

De plus, ce que @ mlc-mlapis a commenté, vous mélangez les opérateurs locables et la méthode de correction de prototype. Utilisez l'un ou l'autre .

Pour votre cas, il devrait être

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.