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


334

У меня проблема с 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"
  ]
}

Http.get не возвращает обещание?
bmm6o

1
@ bmm6o Новый Httpсервис возвращает наблюдаемое
Brocco

1
Я столкнулся с почти идентичной проблемой, пытаясь перевести проект с бета-17 Angular2 на финальную версию. Для меня проблема заключалась в моей IDE, использующей VS 2015, обновление 3. Расширение языковой службы TypeScript все еще 1.8.36работало, тогда как в руководстве по быстрому старту ng2 (как я пишу это) используется "typescript": "^2.0.2". Обновление TS lang. сервис через расширения и обновления сделал свое дело для меня. Во время установки этого обновления я наткнулся на этот SO-ответ , который заканчивается тем же выводом.
Эрик Лиз

Для phpstorm / webstorm, обновление версии машинописи библиотекой моего проекта также решило проблему. Я следовал за шагами этого SO ответа: stackoverflow.com/a/31608934/1291428
Себас

Ответы:


538

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

import 'rxjs/add/operator/map'

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

import 'rxjs/Rx';

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


1
Какие ошибки все еще остаются? Вы можете задать некоторые конкретные вопросы по этому поводу в stackoverflow ;-) Возможно, этот вопрос также может помочь вам: stackoverflow.com/questions/34450131/… .
Тьерри Темплиер

1
Начиная с Angular 2 RC 0, это больше не требуется.
Онур Йылдырым

3
@ OnurYıldırım, используя rc.4, этот импорт все еще требуется, если я не делаю что-то не так.
Джозеф Габриэль

18
Пожалуйста, не используйте 'import' rxjs / Rx ';' потому что он импортирует все и rxjs имеет тенденцию быть довольно большим. Импортируйте операторов по одному, как вам нужно.
Drag0

1
Angular 2 с rxjs: 5.0.0-beta.12 здесь. И я все еще должен был import 'rxjs/add/operator/do'... Пока нам больше не нужно это делать .map(). Но это помогло моему .do()делу, чтобы понять, что мне нужно импортировать его. Спасибо! Один голос от меня :)
MrCroft

82

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

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

Соответственно, Угловое выставляет усеченную версию 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';

2
импорт 'rxjs / Rx'; Вот это да. и все мои волосы мгновенно уходят. я не могу поверить, что это не напечатано во всем мире для Rxjs / Angular2. Спасибо!!!
ДжимБ

Но это часто не задерживается, по умолчанию это импорт из черного списка. Создайте новый угловой CLI-проект, вот увидите. Я сам люблю удобство, но конвенция в местах, где я работаю в Нью-Йорке, не должна это делать.
Тим Консолазио

21

Начиная с версии 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())
    );
}

16

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

Вместо того

import 'rxjs/add/operator/map';

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

import { map } from 'rxjs/operators';

Используя этот подход, теперь в вашей сборке он будет включать только используемые операторы (в данном случае map), ранее он включал в себя все операторы из библиотеки rxjs. проверьте ссылку ниже для более подробной информации. loiane.com/2017/08/angular-rxjs-imports
Шах

13

Использование 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()); // <<--
    }
}

5
Это не очень эффективный подход. Например, если есть несколько подписчиков, каждый из них должен будет запустить карту данных, а не просто сделать это один раз в службе. Я думаю, что у OP был правильный подход, просто не был загружен правильный модуль для его использования.
Эван Плейс

3

Для версий 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


3

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

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

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

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

import 'rxjs/add/operator/map'

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

ionic serve -l

3

Угловая версия 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 в приложении. 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()  )  );
    }

это прекрасно работает удачи!


2

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

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

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

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

import 'rxjs/add/operator/map';

1

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

import 'rxjs/add/operator/map';


1

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

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

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


0

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

import rxjs/add/operator/map;

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



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

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

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


0

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

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


0

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

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


import 'rxjs/Rx';

Это только для того, чтобы вы изначально работали в rxjs 6, выполнив некоторые исправления для вас. Это только кратковременное исправление, и необходимо выполнить полный переход на rxjs 6.
HankCa


0

Плюс к тому, что прокомментировал @ 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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.