带有TypeScript错误http.get(…).map的角度HTTP GET不是[null]中的函数


334

我在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());
    }
}

在中,HallListComponentgetHalls从服务中调用方法:

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 { }

tsconfig.json

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}

http.get不返回承诺吗?
bmm6o

1
@ bmm6o新Http的服务回报可观察到的
Brocco

1
我遇到了几乎相同的问题,试图将项目从Angular2 beta-17迁移到最终版本。我的问题是使用VS 2015 Update 3的IDE。TypeScript语言服务扩展仍在1.8.36,而ng2快速入门指南(在我撰写本文时)正在使用"typescript": "^2.0.2"。升级TS语言。通过扩展和更新提供的服务对我有用。在安装该更新时,我遇到了这个SO答案,结果以相同的结论结束。
埃里克·莱西

对于phpstorm / webstorm,使用我项目的库更新打字稿版本也解决了该问题。我遵循了这个SO答案的步骤:stackoverflow.com/a/31608934/1291428
Sebas 2016年

Answers:


538

我认为您需要导入以下内容:

import 'rxjs/add/operator/map'

或更笼统地说,如果您想拥有更多可观察的方法。 警告:这将导入所有50多个运算符,并将它们添加到您的应用程序中,从而影响捆绑包的大小和加载时间。

import 'rxjs/Rx';

有关更多详细信息,请参见此问题


1
仍然存在哪些错误?您可以在stackoverflow上问一些与此有关的特定问题;-)这个问题也许也对您有帮助:stackoverflow.com/questions/34450131/…
Thierry Templier,2016年

1
从Angular 2 RC 0开始,不再需要此功能。
OnurYıldırım'16

3
@OnurYıldırım,使用rc.4,仍然需要此导入,除非我做错了什么。
约瑟夫·加布里埃尔

18
请不要使用'import'rxjs / Rx';' 因为它会导入所有内容,并且rxjs往往很大。根据需要一对一地导入运算符。
Drag0

1
带有rxjs的Angular 2:5.0.0-beta.12在这里。而且我仍然必须import 'rxjs/add/operator/do'...虽然我们不必再这样做.map()了。但这对我的.do()情况有所帮助,意识到我特别需要将其导入。谢谢!我投了赞成票:)
MrCroft

82

只是一些背景知识...最新开发的Server Communication开发指南(最终)讨论/提及/解释了以下内容:

RxJS库很大。当我们构建生产应用程序并将其部署到移动设备时,大小很重要。我们应该只包括我们实际需要的那些功能。

因此,Angular Observablerxjs/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';

2
导入'rxjs / Rx'; 哇。我的所有头发瞬间消失。我真不敢相信Rxjs / Angular2不会在世界范围内印制。谢谢!!!
JimB

但是它通常不会掉毛,默认情况下是黑名单导入。您将看到创建一个新的角度CLI项目。我自己也很喜欢这种便利,但是在纽约工作的地方却不习惯这样做。
Tim Consolazio

21

rxjs 5.5起,您可以使用管道运算符

import { map } from 'rxjs/operators';

什么是错的 import 'rxjs/add/operator/map';

当我们使用这种方法时,map运算符将被修补observable.prototype 并成为该对象的一部分。

如果稍后,您决定map从处理可观察流的代码中删除运算符,但无法删除相应的import语句,则实现的代码map仍是的一部分Observable.prototype

当捆绑程序尝试消除未使用的代码(aka 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())
    );
}

16

使用Angular 5,RxJS导入得到了改进。

代替

import 'rxjs/add/operator/map';

我们现在可以

import { map } from 'rxjs/operators';

使用这种方法,现在在您的构建中,它将仅包含二手的运算符(在这种情况下为map),之前它包括rxjs库中的所有运算符。检查下面的链接以获取更多详细信息。 loiane.com/2017/08/angular-rxjs-imports
Hiren Shah

13

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()); // <<--
    }
}

5
这不是一个非常有效的方法。例如,如果有多个订阅者,则每个订阅者都必须对数据运行映射,而不是仅在服务中进行一次映射。我认为OP具有正确的方法,只是没有正确的模块来使用它。
Evan Plaice

3

对于Angular 5及更高版本,更新的导入行如下所示:

import { map } from 'rxjs/operators';

要么

import { map } from 'rxjs/operators';

同样,这些版本完全支持Pipable运算符,因此您可以轻松使用.pipe()和.subscribe()。

如果您使用的是Angular版本2,则以下行应绝对正常:

import 'rxjs/add/operator/map';

要么

import 'rxjs/add/operators/map';

如果仍然遇到问题,则必须使用:

import 'rxjs/Rx';

我不希望您直接使用它,因为它会增加加载时间,因为其中包含大量的运算符(有用的和无用的),根据行业规范,这不是一个好习惯,因此请确保您尝试首先使用上述导入行,如果不行,则应使用rxjs / Rx


3

我有这个问题的解决方案

安装此软件包:

npm install rxjs@6 rxjs-compat@6 --save

然后导入这个库

import 'rxjs/add/operator/map'

最终重新启动您的离子项目,然后

ionic serve -l

3

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,应该从中导入它:毕竟,您必须在应用程序中声明HttpModule。 module.ts

import { Http } from '@angular/http';

并且您必须将HttpModule添加到Ngmodule-> 导入

  imports: [
    HttpModule,
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(appRoutes)
  ],

其次要使用地图,您应该首先导入管道:

import { pipe } from 'rxjs';

第三,您需要从中导入map函数:

import { map } from 'rxjs/operators';

您必须在管道内部使用map这样的示例:

 constructor(public http:Http){  }

    getusersGET(){
        return this.http.get('http://jsonplaceholder.typicode.com/users').pipe(
         map(res => res.json()  )  );
    }

祝你好运!


2

您在此处使用的地图不在.map()javascript中,而是Observables在Angular 中运行的Rxjs地图功能...

因此,在这种情况下,如果您想在结果数据上使用map,则需要将其导入...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> 将给定的项目函数应用于源Observable发出的每个值,并将结果值作为Observable发出。

因此,只需像这样导入它:

import 'rxjs/add/operator/map';

1

由于angular2中的Http服务返回的是Observable类型,因此从您的Angular2安装目录(本例中为'node_modules'),我们需要使用http服务将Observable的map函数导入您的组件中,如下所示:

import 'rxjs/add/operator/map';


1

只需在文件中添加该行,

导入'rxjs / Rx';

它将导入一堆依赖项。在角度5中进行了测试





0

发生这种情况是因为您正在使用rxjs,并且rxjs函数中的函数不是静态的,这意味着您不能直接调用它们,而必须调用管道内的方法并从rxjs库中导入该函数

但是,如果您使用的是rxjs-compat,则只需导入rxjs-compat运算符


0

我尝试下面的命令,它得到修复:

npm install rxjs@6 rxjs-compat@6 --save


import 'rxjs/Rx';

那只是通过为您执行一些修补程序来使您最初在rxjs 6中工作。这只是短期修复,应该进行完整的rxjs 6转换。
HankCa


0

加上@ 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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.