【问题标题】:Angular HTTP GET with TypeScript error http.get(...).map is not a function in [null]带有 TypeScript 错误的 Angular HTTP GET http.get(...).map 不是 [null] 中的函数
【发布时间】:2016-04-03 13:56:30
【问题描述】:

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

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"
  ]
}

【问题讨论】:

  • http.get 不返回一个承诺吗?
  • @bmm6o 新的 Http 服务返回一个 observable
  • 我遇到了一个几乎相同的问题,试图将项目从 Angular2 beta-17 迁移到最终版本。对我来说,问题是我的 IDE,使用 VS 2015,Update 3。TypeScript 语言服务扩展仍然在1.8.36,而 ng2 快速入门指南(在我写这篇文章时)使用的是"typescript": "^2.0.2"。升级 TS 语言。通过扩展和更新提供的服务对我有用。在安装该更新时,我遇到了this SO answer,它以相同的结论结束。
  • 对于phpstorm/webstorm,用我项目的库更新typescript版本也解决了这个问题。我遵循了这个 SO 答案的步骤:stackoverflow.com/a/31608934/1291428

标签: angular rxjs


【解决方案1】:

我认为你需要导入这个:

import 'rxjs/add/operator/map'

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

import 'rxjs/Rx';

更多详情请见this issue

【讨论】:

  • 哪些错误仍然存​​在?您可以在 stackoverflow 上提出一些与此相关的具体问题 ;-) 这个问题也可能对您有所帮助:stackoverflow.com/questions/34450131/….
  • 从 Angular 2 RC 0 开始,这不再是必需的。
  • @OnurYıldırım,使用 rc.4,仍然需要此导入,除非我做错了什么。
  • 请不要使用'import 'rxjs/Rx';'因为它导入了所有东西,而且 rxjs 往往很大。根据需要一一导入操作符。
  • Angular 2 与 rxjs:5.0.0-beta.12 在这里。我仍然必须import 'rxjs/add/operator/do'...虽然我们不必再为.map() 这样做了。但这有助于我的.do() 案例,让我意识到我特别需要导入它。谢谢!我投了一票:)
【解决方案2】:

只是一些背景... 新创建的Server Communication 开发指南(最后)讨论/提及/解释了这一点:

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

因此,Angular 在rxjs/Observable 模块中公开了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/Rx';哇。我所有的头发都立即消失了。我不敢相信这不是为 Rxjs/Angular2 打印在世界各地的。谢谢!!!
  • 但它通常不会 lint,默认情况下它是列入黑名单的导入。创建一个新的 Angular CLI 项目,你会看到。我自己也喜欢这种便利,但我在纽约工作的地方的惯例是不这样做。
【解决方案3】:

rxjs 5.5 开始,你可以使用 pipeable 操作符

import { map } from 'rxjs/operators';

有什么问题 import 'rxjs/add/operator/map';

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

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

当打包程序试图消除未使用的代码(aka tree shaking)时,他们可能会决定将 map 运算符的代码保留在 Observable 中,即使它没有在 Observable 中使用。应用。

解决方案 - Pipeable operators

Pipeable 运算符是纯函数,不会修补 Observable。您可以使用 ES6 导入语法 import { map } from "rxjs/operators" 导入运算符,然后将它们包装到一个函数 pipe() 中,该函数采用可变数量的参数,即可链接的运算符。

类似这样的:

getHalls() {
    return this.http.get(HallService.PATH + 'hall.json')
    .pipe(
        map((res: Response) => res.json())
    );
}

【讨论】:

  • 是的,现在使用 Rxjs 版本 7+,建议通过使用管道来使用可管道运算符,很好的一个,我发现所有以前的答案都是旧的,并且没有更新到当前版本的 Angular 和 Rxjs
【解决方案4】:

Angular 5 改进了 RxJS 导入。

代替

import 'rxjs/add/operator/map';

我们现在可以

import { map } from 'rxjs/operators';

【讨论】:

  • 使用这种方法,现在在你的构建中它只会包含使用过的操作符(在这种情况下是 map),之前它包含了 rxjs 库中的所有操作符。查看下面的链接了解更多详情。 loiane.com/2017/08/angular-rxjs-imports
【解决方案5】:

直接使用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()); // <<--
    }
}

【讨论】:

  • 这不是一个非常有效的方法。例如,如果有多个订阅者,他们每个人都必须在数据上运行 map,而不是只在服务中执行一次。我认为 OP 有正确的方法,只是没有加载正确的模块来使用它。
【解决方案6】:

对于 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

【讨论】:

    【解决方案7】:

    我有办法解决这个问题

    安装这个包:

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

    然后导入这个库

    import 'rxjs/add/operator/map'
    

    最后重启你的 ionic 项目然后

    ionic serve -l
    

    【讨论】:

      【解决方案8】:

      您在这里使用的 ma​​p 不是 javascript 中的 .map(),它是 Rxjs 映射函数,它在 Angular 中作用于 Observables...

      所以在这种情况下,如果您想在结果数据上使用地图,则需要导入它...

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

      所以只需像这样导入它:

      import 'rxjs/add/operator/map';
      

      【讨论】:

        【解决方案9】:

        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 哟应该从以下位置导入它: 毕竟你必须在 app.module.ts 中声明 HttpModule

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

        你必须将 HttpModule 添加到 Ngmodule -> imports

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

        效果很好,祝你好运!

        【讨论】:

          【解决方案10】:

          由于 angular2 中的 Http 服务返回一个 Observable 类型, 从你的Angular2安装目录(在我的例子中是'node_modules'),我们需要使用http服务在你的组件中导入Observable的map函数,如:

          import 'rxjs/add/operator/map';
          

          【讨论】:

            【解决方案11】:

            Angular 6 - 只有 import 'rxjs/Rx' 对我有用

            【讨论】:

              【解决方案12】:

              只需在文件中添加该行,

              导入'rxjs/Rx';

              它将导入一堆依赖项。在 Angular 5 中测试

              【讨论】:

                【解决方案13】:

                没错,RxJs 已将其 map 运算符分离到一个单独的模块中,现在您需要像任何其他运算符一样显式导入它。

                import rxjs/add/operator/map;

                你会没事的。

                【讨论】:

                  【解决方案14】:

                  全局导入是安全的。

                  导入'rxjs/Rx';

                  【讨论】:

                    【解决方案15】:
                    import 'rxjs/add/operator/map';
                    

                    将解决您的问题

                    我在 Angular 5.2.0 和 rxjs 5.5.2 中对其进行了测试

                    【讨论】:

                      【解决方案16】:

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

                      但是如果你使用的是 rxjs-compat 那么你只需要导入 rxjs-compat 操作符

                      【讨论】:

                        【解决方案17】:

                        我尝试了以下命令,它得到了修复:

                        npm install rxjs@6 rxjs-compat@6 --save
                        
                        
                        import 'rxjs/Rx';
                        

                        【讨论】:

                        • 这只是为了让您在 rxjs 6 中通过为您执行一些修补程序开始工作。这只是一个短期修复,应该进行完整的 rxjs 6 转换。
                        【解决方案18】:

                        从 'rxjs/operators' 导入 { map };

                        这在角度 8 中对我有用

                        【讨论】:

                          【解决方案19】:

                          加上 @mlc-mapis 评论的内容,您正在混合 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

                          【讨论】:

                            猜你喜欢
                            • 2020-02-28
                            • 2017-12-20
                            • 2019-08-18
                            • 2016-10-02
                            • 1970-01-01
                            • 2023-04-09
                            • 2015-11-04
                            • 2017-05-02
                            相关资源
                            最近更新 更多