HTTP GET angular con error de TypeScript http.get (...) .map no es una función en [nulo]


334

Tengo un problema con HTTP en Angular.

Solo quiero GETuna JSONlista y mostrarla en la vista.

Clase de servicio

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

Y en el HallListComponentllamo al getHallsmétodo desde el servicio:

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

Sin embargo, obtuve una excepción:

TypeError: this.http.get (...). Map no es una función en [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 no devuelve una promesa?
bmm6o

1
@ bmm6o El nuevo Httpservicio devuelve un observable
Brocco

1
Me encontré con un problema casi idéntico, tratando de migrar un proyecto de Angular2 beta-17 a la versión final. Sin embargo, el problema para mí fue mi IDE, usando VS 2015, Actualización 3. La extensión del servicio de lenguaje TypeScript todavía estaba en 1.8.36, mientras que la guía de inicio rápido ng2 (mientras escribo esto) está usando "typescript": "^2.0.2". Actualización del TS lang. el servicio a través de Extensiones y Actualizaciones me sirvió. Mientras se instalaba esa actualización, encontré esta respuesta SO , que termina con la misma conclusión.
Eric Lease

Para phpstorm / webstorm, la actualización de la versión mecanografiada con la biblioteca de mi proyecto también resolvió el problema. Seguí los pasos de esta respuesta SO: stackoverflow.com/a/31608934/1291428
Sebas

Respuestas:


538

Creo que necesitas importar esto:

import 'rxjs/add/operator/map'

O, más generalmente, esto si desea tener más métodos para observables. ADVERTENCIA: Esto importará los más de 50 operadores y los agregará a su aplicación, lo que afectará el tamaño de su paquete y los tiempos de carga.

import 'rxjs/Rx';

Vea este número para más detalles.


1
¿Qué errores aún quedan? Puede hacer algunas preguntas específicas con respecto a esto en stackoverflow ;-) Esta pregunta quizás podría ayudarlo también: stackoverflow.com/questions/34450131/… .
Thierry Templier

1
A partir de Angular 2 RC 0, esto ya no es necesario.
Onur Yıldırım

3
@ OnurYıldırım, usando rc.4, esta importación aún es necesaria, a menos que esté haciendo algo mal.
Joseph Gabriel

18
Por favor, no use 'import' rxjs / Rx ';' porque importa todo y rxjs tiende a ser bastante grande. Importa operadores uno por uno cuando los necesites.
Drag0

1
Angular 2 con rxjs: 5.0.0-beta.12 aquí. Y todavía tenía que import 'rxjs/add/operator/do'... Aunque ya no tenemos que hacer esto por .map()más tiempo. Pero esto ayudó a mi .do()caso, para darme cuenta de que específicamente necesito importarlo. ¡Gracias! Un voto mío :)
MrCroft

82

Solo algunos antecedentes ... La nueva guía de desarrollo de Server Communication (finalmente) discute / menciona / explica esto:

La biblioteca RxJS es bastante grande. El tamaño importa cuando creamos una aplicación de producción y la implementamos en dispositivos móviles. Deberíamos incluir solo aquellas características que realmente necesitamos.

En consecuencia, Angular expone una versión reducida Observabledel rxjs/Observablemódulo, una versión que carece de casi todos los operadores, incluidos los que nos gustaría usar aquí, como elmap método.

Depende de nosotros agregar los operadores que necesitamos. Podríamos agregar cada operador, uno por uno, hasta que tengamos una implementación Observable personalizada ajustada con precisión a nuestros requisitos.

Entonces, como @Thierry ya respondió, podemos atraer a los operadores que necesitamos:

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

O, si somos flojos, podemos atraer al conjunto completo de operadores. ADVERTENCIA: esto agregará los más de 50 operadores a su paquete de aplicaciones y afectará los tiempos de carga

import 'rxjs/Rx';

2
importar 'rxjs / Rx'; Guau. y todo mi cabello tirando al instante desaparece. No puedo creer que esto no se imprima en todo el mundo para Rxjs / Angular2. ¡¡¡Gracias!!!
JimB

Pero con frecuencia no produce pelusas, por defecto es una importación en la lista negra. Cree un nuevo proyecto CLI angular, ya lo verá. Me encanta la comodidad, pero la convención en los lugares donde trabajo en Nueva York no es para hacerlo.
Tim Consolazio

21

A partir de rxjs 5.5 en adelante, puede usar los operadores canalizables

import { map } from 'rxjs/operators';

¿Qué está mal con el import 'rxjs/add/operator/map';

Cuando usamos este enfoque, el mapoperador será parcheado observable.prototype y se convertirá en parte de este objeto.

Si más adelante, decide eliminar el mapoperador del código que maneja la secuencia observable pero no elimina la instrucción de importación correspondiente, el código que implementa mapsigue siendo parte de la Observable.prototype.

Cuando los agrupadores intentan eliminar el código no utilizado ( también conocido como tree shaking ), pueden decidir mantener el código del mapoperador en el Observable aunque no se esté utilizando en la aplicación.

solución -Pipeable operators

Los operadores canalizables son funciones puras y no parchean el Observable . Puede importar operadores utilizando la sintaxis de importación ES6 import { map } from "rxjs/operators"y luego envolverlos en una funciónpipe() que tome un número variable de parámetros, es decir, operadores encadenables.

Algo como esto:

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

16

Con Angular 5 se mejora la importación de RxJS.

En vez de

import 'rxjs/add/operator/map';

Ahora podemos

import { map } from 'rxjs/operators';

Usando este enfoque, ahora en su compilación solo incluirá operadores usados ​​(mapa en este caso), anteriormente incluía todos los operadores de la biblioteca rxjs. consulte el siguiente enlace para obtener más detalles. loiane.com/2017/08/angular-rxjs-imports
Hiren Shah

13

Usar Observable.subscribedirectamente debería funcionar.

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

55
Este no es un enfoque muy eficiente. Por ejemplo, si hay varios suscriptores, cada uno tendrá que ejecutar un mapa en los datos, en lugar de hacerlo una sola vez en el servicio. Creo que OP tenía el enfoque correcto, simplemente no tenía el módulo correcto cargado para usarlo.
Evan Plaice el

3

Para las versiones angulares 5 y superiores, la línea de importación actualizada se ve así:

import { map } from 'rxjs/operators';

O

import { map } from 'rxjs/operators';

Además, estas versiones son totalmente compatibles con los operadores Pipable para que pueda usar fácilmente .pipe () y .subscribe ().

Si está utilizando Angular versión 2, entonces la siguiente línea debería funcionar absolutamente bien:

import 'rxjs/add/operator/map';

O

import 'rxjs/add/operators/map';

Si aún encuentra un problema, debe ir con:

import 'rxjs/Rx';

No preferiré que lo use directamente porque aumenta el tiempo de carga, ya que tiene una gran cantidad de operadores (útiles y no útiles), lo que no es una buena práctica de acuerdo con las normas de la industria, así que asegúrese de intente usar primero las líneas de importación mencionadas anteriormente, y si eso no funciona, entonces debería usar rxjs / Rx


3

Tengo una solución a este problema.

Instala este paquete:

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

luego importe esta biblioteca

import 'rxjs/add/operator/map'

finalmente reinicie su proyecto iónico luego

ionic serve -l

3

Versión angular 6 "0.6.8" rxjs versión 6 "^ 6.0.0"

esta solución es para:

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

como todos sabemos, angular se está desarrollando todos los días, por lo que hay muchos cambios todos los días y esta solución es para que angular 6 y rxjs 6 trabajen
primero con http, debe importarlo: después de todo, debe declarar el HttpModule en la aplicación. module.ts

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

y tienes que agregar HttpModule a Ngmodule -> importaciones

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

segundo para trabajar con el mapa, primero debe importar la tubería:

import { pipe } from 'rxjs';

tercero, necesita importar la función de mapa desde:

import { map } from 'rxjs/operators';

tienes que usar map inside pipe como este ejemplo:

 constructor(public http:Http){  }

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

eso funciona perfectamente buena suerte!


2

El mapa que usa aquí, no está .map()en javascript, es la función de mapa Rxjs que está trabajando enObservables en Angular ...

Entonces, en ese caso, debe importarlo si desea usar el mapa en los datos de resultados ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Aplica una función de proyecto determinada a cada valor emitido por el Observable de origen y emite los valores resultantes como un Observable.

Así que simplemente impórtalo así:

import 'rxjs/add/operator/map';

1

Ya que servicio Http en angular2 devuelve un tipo Observable , desde su directorio de instalación Angular2 ('node_modules' en mi caso), necesitamos importar la función de mapa del Observable en su componente usando el servicio http , como:

import 'rxjs/add/operator/map';


1

Simplemente agregue la línea en su archivo,

importar 'rxjs / Rx';

Importará un montón de dependencias. Probado en angular 5


0

Es cierto que RxJs ha separado su operador de mapa en un módulo separado y ahora necesita importarlo explícitamente como cualquier otro operador.

import rxjs/add/operator/map;

y estarás bien



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

resolverá tu problema

Lo probé en angular 5.2.0 y rxjs 5.5.2


0

esto está sucediendo porque está utilizando los rxjs y en la función rxjs no son estáticos, lo que significa que no puede llamarlos directamente, debe llamar a los métodos dentro de la tubería e importar esa función desde la biblioteca rxjs

Pero si está utilizando rxjs-compat, entonces solo necesita importar los operadores rxjs-compat


0

Intenté los siguientes comandos y se solucionó:

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


import 'rxjs/Rx';

Eso es solo para que trabajes inicialmente en rxjs 6 realizando algunos parches para ti. Es solo una solución a corto plazo y se debe realizar la transición completa de rxjs 6.
HankCa


0

Además de lo que comentó @ mlc-mlapis, estás mezclando operadores que se pueden alquilar y el método de parcheo prototipo. Use uno u otro .

Para su caso debería ser

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.