У меня проблема с 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]
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{}
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 { }
{
"compilerOptions": {
"target": "ES5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules"
]
}
Я думаю, что вам нужно импортировать это:
import 'rxjs/add/operator/map'
Или, в общем, это, если вы хотите иметь больше методов для наблюдаемых. ПРЕДУПРЕЖДЕНИЕ. Это импортирует все 50+ операторов и добавит их в ваше приложение, что повлияет на размер вашего пакета и время загрузки.
import 'rxjs/Rx';
Подробнее см. эту проблему.
Просто какой-то фон... Недавно отчеканенный 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';
Использование 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 импорт RxJS улучшен.
Вместо
import 'rxjs/add/operator/map';
Теперь мы можем
import { map } from 'rxjs/operators';
Используемая здесь карта не является .map()
в javascript, это функция отображения Rxjs, работающая на Observables
в Angular...
Итак, в этом случае вам нужно импортировать его, если вы хотите использовать карту в результирующих данных...
map(project: function(value: T, index: number): R, thisArg: any): Observable<R>
Применяет заданную функцию проекта к каждому испускаемому значению с помощью источника Observable и испускает результирующие значения в виде Наблюдаемое.
Поэтому просто импортируйте его следующим образом:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/map';
решит вашу проблему
Я тестировал его в angular 5.2.0 и rxjs 5.5.2
Глобальный импорт безопасен.
import 'rxjs/Rx';
Так как служба Http в angular2 возвращает Наблюдаемый тип, Из вашего каталога установки Angular2 ('node_modules' в моем случае) нам нужно импортировать функцию отображения Observable в компоненте с помощью службы http, как:
import 'rxjs/add/operator/map';
Правда, RxJs отделил оператор отображения в отдельном модуле, и теперь вам нужно явно импортировать его, как и любой другой оператор.
import rxjs/add/operator/map;
и все будет хорошо.
Http
возвращает наблюдаемый