Угловой HTTP GET с ошибкой TypeScript http.get(...). Map не является функцией в [null]

У меня проблема с HTTP в Angular.

я всего-лишь хочу GET JSON список и показать его в представлении.

Сервисный класс

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

И в HallListComponent Я звоню getHalls метод из сервиса:

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

Однако я получил исключение:

Ошибка типа: this.http.get (...). Map не является функцией в [null]

зал-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"
  ]
}

16 ответов

Решение

Я думаю, что вам нужно импортировать это:

import 'rxjs/add/operator/map'

Или, в общем, это, если вы хотите иметь больше методов для наблюдаемых.ВНИМАНИЕ: Это импортирует все более 50 операторов и добавляет их в ваше приложение, что влияет на размер вашего пакета и время загрузки.

import 'rxjs/Rx';

Смотрите эту проблему для более подробной информации.

Просто некоторая предыстория... Недавно разработанное руководство по разработке серверных коммуникаций (наконец) обсуждает / упоминает / объясняет это:

Библиотека RxJS довольно большая. Размер имеет значение, когда мы создаем производственное приложение и разворачиваем его на мобильных устройствах. Мы должны включать только те функции, которые нам действительно нужны.

Соответственно, Angular предоставляет урезанную версию Observable в rxjs/Observable модуль, версия, в которой отсутствуют почти все операторы, включая те, которые мы хотели бы использовать здесь, такие как map метод.

Мы должны добавить нужные нам операторы. Мы могли бы добавлять каждого оператора по очереди, пока у нас не будет настраиваемой реализации Observable, точно соответствующей нашим требованиям.

Так как @Thierry уже ответил, мы можем просто добавить нужные нам операторы:

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

Или, если мы ленивы, мы можем использовать полный набор операторов. ВНИМАНИЕ: это добавит все 50+ операторов в ваш пакет приложений и повлияет на время загрузки

import 'rxjs/Rx';

Начиная с версии rxjs 5.5, вы можете использовать конвейерные операторы

import { map } from 'rxjs/operators';

Что не так с import 'rxjs/add/operator/map';

Когда мы используем этот подход map Оператор будет исправлен на observable.prototype и становится частью этого объекта.

Если позже вы решите удалить map оператор из кода, который обрабатывает наблюдаемый поток, но не может удалить соответствующий оператор импорта, код, который реализует map остается частью Observable.prototype,

Когда упаковщики пытаются устранить неиспользуемый код (иначе tree shaking), они могут решить сохранить код map оператор в Observable, даже если он не используется в приложении.

Решение - Pipeable operators

Трубные операторы являются чистыми функциями и не исправляют Observable. Вы можете импортировать операторы, используя синтаксис импорта ES6 import { map } from "rxjs/operators" а затем обернуть их в функцию pipe() это принимает переменное число параметров, то есть цепочечные операторы.

Что-то вроде этого:

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

С Angular 5 улучшен импорт RxJS.

Вместо

import 'rxjs/add/operator/map';

Мы можем сейчас

import { map } from 'rxjs/operators';

С помощью Observable.subscribe напрямую должно работать.

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

Для версий Angular 5 и выше обновленная строка импорта выглядит следующим образом:

import { map } from 'rxjs/operators';

ИЛИ ЖЕ

import { map } from 'rxjs/operators';

Также эти версии полностью поддерживают Pipable Operators, поэтому вы можете легко использовать.pipe() и.subscribe().

Если вы используете Angular версии 2, то следующая строка должна работать абсолютно нормально:

import 'rxjs/add/operator/map';

ИЛИ ЖЕ

import 'rxjs/add/operators/map';

Если вы все еще сталкиваетесь с проблемой, тогда вы должны пойти с:

import 'rxjs/Rx';

Я не предпочту, чтобы вы использовали его напрямую, потому что он увеличивает время загрузки, поскольку в нем большое количество операторов (полезных и бесполезных), что не является хорошей практикой в ​​соответствии с отраслевыми нормами, поэтому убедитесь, что сначала вы пытаетесь использовать вышеупомянутые строки импорта, и если это не сработает, тогда вам следует перейти на rxjs/Rx

Карта, которую вы используете здесь, не является .map() в JavaScript это функция карты Rxjs, которая работает на Observables в угловых...

Так что в этом случае вам нужно импортировать его, если вы хотите использовать карту на данных результатов...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Применяет заданную функцию проекта к каждому значению, излучаемому исходной наблюдаемой, и выводит полученные значения в качестве наблюдаемой.

Просто импортируйте это так:

import 'rxjs/add/operator/map';

У меня есть решение этой проблемы

Установите этот пакет:

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

затем импортируйте эту библиотеку

import 'rxjs/add/operator/map'

наконец перезапустите свой ионный проект, то

ionic serve -l

Угловая версия 6 "0.6.8" rxjs версия 6 "^6.0.0"

это решение для:

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

как все мы знаем, angular разрабатывается каждый день, поэтому каждый день происходит множество изменений, и это решение предназначено для angular 6 и rxjs 6
сначала для работы с http вы должны импортировать его из: в конце концов вы должны объявить HttpModule в app.module.ts

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

и вы должны добавить HttpModule в Ngmodule -> импорт

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

Во-вторых, для работы с картой вы должны сначала импортировать канал:

import { pipe } from 'rxjs';

в-третьих, вам нужно импортировать функцию карты из:

import { map } from 'rxjs/operators';

Вы должны использовать карту внутри трубы, как этот пример:

 constructor(public http:Http){  }

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

это работает отлично, удачи!

Angular 6 - только импорт 'rxjs/Rx' помог мне

Просто добавьте строку в ваш файл,

импорт 'rxjs/Rx';

Он будет импортировать кучу зависимостей. Испытано в угловых 5

Так как служба Http в angular2 возвращает тип Observable, из вашего установочного каталога Angular2 (в моем случае это "node_modules"), нам нужно импортировать функцию отображения Observable в ваш компонент, используя службу http, как:

import 'rxjs/add/operator/map';

Глобальный импорт безопасен.

импорт 'rxjs/Rx';

import 'rxjs/add/operator/map';

решит вашу проблему

Я проверил это в угловых 5.2.0 и rxjs 5.5.2

Я попробовал ниже команды, и это исправлено:

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


import 'rxjs/Rx';

Импортировать {карту} из 'rxjs/operator';

это работает для меня в angular 8

Правда, RxJs отделил свой оператор отображения в отдельном модуле, и теперь вам нужно экспортировать его, как любой другой оператор.

import rxjs/add/operator/map;

и у тебя все будет хорошо.

Плюс то, что прокомментировал @ mlc-mlapis, вы смешиваете lettable-операторы и метод исправления прототипа. Используйте то или другое.

Для вашего случая это должно быть

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

Это происходит потому, что вы используете функцию rxjs, а функция rxjs не является статической, что означает, что вы не можете вызывать их напрямую, вы должны вызывать методы внутри канала и импортировать эту функцию из библиотеки rxjs.

Но если вы используете rxjs-compat, то вам просто нужно импортировать операторы rxjs-compat

Другие вопросы по тегам