Angular HTTP GET с ошибкой TypeScript http.get(...). map не является функцией в [null]
У меня проблема с 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"
]
}
Ответы
Ответ 1
Я думаю, что вам нужно импортировать это:
import 'rxjs/add/operator/map'
Или, в общем, это, если вы хотите иметь больше методов для наблюдаемых.
ПРЕДУПРЕЖДЕНИЕ. Это импортирует все 50+ операторов и добавит их в ваше приложение, что повлияет на размер вашего пакета и время загрузки.
import 'rxjs/Rx';
Подробнее см. эту проблему.
Ответ 2
Просто какой-то фон... Недавно отчеканенный 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';
Ответ 3
Использование 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()); // <<--
}
}
Ответ 4
При использовании Angular 5 импорт RxJS улучшен.
Вместо
import 'rxjs/add/operator/map';
Теперь мы можем
import { map } from 'rxjs/operators';
Ответ 5
Используемая здесь карта не является .map()
в javascript, это функция отображения Rxjs, работающая на Observables
в Angular...
Итак, в этом случае вам нужно импортировать его, если вы хотите использовать карту в результирующих данных...
map(project: function(value: T, index: number): R, thisArg: any):
Observable<R>
Применяет заданную функцию проекта к каждому испускаемому значению с помощью источника Observable и испускает результирующие значения в виде Наблюдаемое.
Поэтому просто импортируйте его следующим образом:
import 'rxjs/add/operator/map';
Ответ 6
Так как служба Http в angular2 возвращает Наблюдаемый тип,
Из вашего каталога установки Angular2 ('node_modules' в моем случае) нам нужно импортировать функцию отображения Observable в компоненте с помощью службы http, как:
import 'rxjs/add/operator/map';
Ответ 7
Глобальный импорт безопасен.
import 'rxjs/Rx';
Ответ 8
import 'rxjs/add/operator/map';
решит вашу проблему
Я тестировал его в angular 5.2.0 и rxjs 5.5.2
Ответ 9
Правда, RxJs отделил оператор отображения в отдельном модуле, и теперь вам нужно явно импортировать его, как и любой другой оператор.
import rxjs/add/operator/map;
и все будет хорошо.