Угловой 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() ) );
}
это работает отлично, удачи!
Просто добавьте строку в ваш файл,
импорт 'rxjs/Rx';
Он будет импортировать кучу зависимостей. Испытано в угловых 5
Так как служба Http в angular2 возвращает тип Observable, из вашего установочного каталога Angular2 (в моем случае это "node_modules"), нам нужно импортировать функцию отображения Observable в ваш компонент, используя службу http, как:
import 'rxjs/add/operator/map';
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