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

239

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

Я просто хочу GET a 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;
        });
    }
}

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

TypeError: 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"
  ]
}
  • 0
    Http.get не возвращает обещание?
  • 1
    @ bmm6o Новый сервис Http возвращает наблюдаемый
Показать ещё 2 комментария
Теги:
angular
rxjs

9 ответов

434
Лучший ответ

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

import 'rxjs/add/operator/map'

Или, в общем, это, если вы хотите иметь больше методов для наблюдаемых. ПРЕДУПРЕЖДЕНИЕ. Это импортирует все 50+ операторов и добавит их в ваше приложение, что повлияет на размер вашего пакета и время загрузки.

import 'rxjs/Rx';

Подробнее см. эту проблему.

  • 1
    Какие ошибки все еще остаются? Вы можете задать некоторые конкретные вопросы по этому поводу в stackoverflow ;-) Возможно, этот вопрос также может помочь вам: stackoverflow.com/questions/34450131/… .
  • 1
    Начиная с Angular 2 RC 0, это больше не требуется.
Показать ещё 7 комментариев
75

Просто какой-то фон... Недавно отчеканенный Server Communication dev guide (наконец) обсуждает/упоминает/объясняет это:

Библиотека 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';
  • 2
    импорт 'rxjs / Rx'; Вот это да. и все мои волосы мгновенно уходят. я не могу поверить, что это не напечатано во всем мире для Rxjs / Angular2. Спасибо!!!
  • 0
    Но это часто не задерживается, по умолчанию это импорт из черного списка. Создайте новый угловой CLI-проект, вот увидите. Я сам люблю удобство, но конвенция в местах, где я работаю в Нью-Йорке, не должна это делать.
10

Использование 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 был правильный подход, просто не был загружен правильный модуль для его использования.
8

При использовании Angular 5 импорт RxJS улучшен.

Вместо

import 'rxjs/add/operator/map';

Теперь мы можем

import { map } from 'rxjs/operators';
  • 0
    Есть ли преимущество в этом подходе? Выглядит действительно интересно.
  • 0
    Используя этот подход, теперь в вашей сборке он будет включать только используемые операторы (в данном случае map), ранее он включал в себя все операторы из библиотеки rxjs. проверьте ссылку ниже для более подробной информации. loiane.com/2017/08/angular-rxjs-imports
1

Используемая здесь карта не является .map() в javascript, это функция отображения Rxjs, работающая на Observables в Angular...

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

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

Поэтому просто импортируйте его следующим образом:

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

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

Я тестировал его в angular 5.2.0 и rxjs 5.5.2

0

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

import 'rxjs/Rx';

0

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

import 'rxjs/add/operator/map';
-1

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

import rxjs/add/operator/map;

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню