我在Angular中使用HTTP有问题。
我只想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;
});
}
}
但是,我得到了一个例外:
TypeError: this.http.get(...(.映射不是 [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{}
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"
]
}
我认为您需要导入这个:
import 'rxjs/add/operator/map'
或者更一般地说,如果你想有更多的可观察量方法。警告:这将导入所有 50+ 运算符并将它们添加到您的应用程序中,从而影响您的捆绑包大小和加载时间。
import 'rxjs/Rx';
有关更多详细信息,请参阅此问题。
只是一些背景...新发布的服务器通信开发指南(最后(讨论/提及/解释了这一点:
RxJS库非常大。当我们构建生产应用程序并将其部署到移动设备时,大小很重要。我们应该只包含我们实际需要的那些功能。
因此,Angular 在
rxjs/Observable
模块中公开了Observable
的精简版本,该版本几乎缺少所有运算符,包括我们在这里想要使用的运算符,例如map
方法。由我们来添加所需的运算符。我们可以逐个添加每个运算符,直到我们有一个自定义的可观察实现,精确地调整到我们的要求。
因此,正如@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
运算符,但未能删除相应的 import 语句,则实现map
的代码仍然是Observable.prototype
的一部分。
当捆绑器试图消除未使用的代码(又名tree shaking
(时,他们可能会决定将map
运算符的代码保留在可观察量中,即使它没有在应用程序中使用。
解决方案 - Pipeable operators
管道运算符是纯函数,不会修补可观察量。您可以使用 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 Operator,因此您可以轻松使用.pipe((和.subscribe((。
如果您使用的是 Angular 版本 2,那么以下行应该绝对可以正常工作:
import 'rxjs/add/operator/map';
或
import 'rxjs/add/operators/map';
如果仍然遇到问题,则必须使用:
import 'rxjs/Rx';
我不希望你直接使用它,因为它会增加加载时间,因为它有大量的运算符(有用和无用的(,根据行业标准,这不是一个好的做法,所以请确保你先尝试使用上面提到的导入行,如果这不起作用,那么你应该选择 rxjs/Rx
我有解决这个问题的方法
安装此软件包:
npm install rxjs@6 rxjs-compat@6 --save
然后导入此库
import 'rxjs/add/operator/map'
最后重新启动您的离子项目
ionic serve -l
你在这里使用的地图不是JavaScript中的.map()
,而是Rxjs地图函数,它在Angular中处理Observables
。
因此,在这种情况下,如果您想在结果数据上使用地图,则需要导入它。
map(project: function(value: T, index: number): R, thisArg: any): Observable<R>
将给定的项目函数应用于发出的每个值由源 Observable,并将结果值作为观察。
所以只需像这样导入它:
import 'rxjs/add/operator/map';
Angular 版本 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 yo 应该从以下位置导入它: 毕竟你必须在app.module.ts中声明HttpModule。
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() ) );
}
这完全祝你好运!
由于 angular2 中的 Http 服务返回一个 Observable 类型,从您的 Angular2 安装目录(在我的例子中为"node_modules"(,我们需要使用 http 服务在您的组件中导入 Observable 的映射函数,如:
import 'rxjs/add/operator/map';
Angular 6 - 只有import 'rxjs/Rx'
为我做了这个技巧
只需在文件中添加该行,
import 'rxjs/Rx';
它将导入一堆依赖项。在角度 5
没错,RxJs 已将其映射运算符分离到一个单独的模块中,现在您需要像任何其他运算符一样显式导入它。
import rxjs/add/operator/map;
你会没事的。
全局导入是安全的。
import 'rxjs/Rx';
import 'rxjs/add/operator/map';
将解决您的问题
我在 angular 5.2.0 和 rxjs 5.5.2 中对其进行了测试
发生这种情况是因为您正在使用 rxjs 并且在 rxjs 函数中不是静态的,这意味着您不能直接调用它们,您必须调用管道内的方法并从 rxjs 库中导入该函数
但是如果你使用的是rxjs-compat,那么你只需要导入rxjs-compat运算符
我尝试了以下命令,它得到了修复:
npm install rxjs@6 rxjs-compat@6 --save
import 'rxjs/Rx';
从 'rxjs/operators ' 导入 { map };
这在角度 8 中对我有用
加上@mlc-mlapis 的评论,您混合了可出租运算符和原型修补方法。使用其中之一。
对于您的情况,应该是
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