Angular HTTP GET 与 TypeScript 错误 http.get(..).映射不是 [null] 中的

Angular HTTP GET with TypeScript error http.get(...).map is not a function in [null]

本文关键字:映射 null 中的 GET HTTP TypeScript 错误 get http Angular      更新时间:2023-09-26

我在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

全局导入是安全的。

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