HTTP เชิงมุม GET พร้อมข้อผิดพลาด TypeScript http.get (…) .map ไม่ใช่ฟังก์ชันใน [null]


334

ฉันมีปัญหากับ HTTP ในเชิงมุม

ผมแค่อยากจะรายการและแสดงในมุมมองGETJSON

ระดับบริการ

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]

ห้องโถง 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"
  ]
}

http.get ส่งคืนสัญญาหรือไม่
bmm6o

1
@ bmm6o Httpบริการใหม่ส่งคืนสิ่งที่สังเกตได้
Brocco

1
ฉันพบปัญหาที่เหมือนกันเกือบจะพยายามย้ายโครงการจาก Angular2 beta-17 ไปเป็นรุ่นสุดท้าย ปัญหาสำหรับฉันเป็น IDE ของฉันแม้ว่าการใช้ VS 2015 ปรับปรุง 3. typescript บริการส่วนขยายของภาษาก็ยังคงที่1.8.36ในขณะที่เป็นคู่มือ NG2 QuickStart (ตามที่ผมเขียนนี้) "typescript": "^2.0.2"คือการใช้ การอัพเกรด TS lang บริการผ่านส่วนขยายและการอัปเดตได้หลอกลวงฉัน ในขณะที่ติดตั้งการอัปเดตฉันพบคำตอบ SO นี้ซึ่งจบลงด้วยข้อสรุปเดียวกัน
Eric Lease

สำหรับ phpstorm / webstorm การอัปเดตเวอร์ชัน typescript ด้วยไลบรารีของโครงการของฉันก็ช่วยแก้ไขปัญหาได้เช่นกัน ฉันทำตามขั้นตอนของคำตอบ SO นี้แล้ว: stackoverflow.com/a/31608934/1291428
Sebas

คำตอบ:


538

ฉันคิดว่าคุณต้องนำเข้าสิ่งนี้:

import 'rxjs/add/operator/map'

หรือมากกว่านี้โดยทั่วไปหากคุณต้องการมีวิธีการเพิ่มเติมสำหรับการสังเกต คำเตือน: สิ่งนี้จะนำเข้าตัวดำเนินการมากกว่า 50 รายและเพิ่มไปยังแอปพลิเคชันของคุณซึ่งจะส่งผลกระทบต่อขนาดมัดและเวลาในการโหลด

import 'rxjs/Rx';

ดูปัญหานี้สำหรับรายละเอียดเพิ่มเติม


1
ข้อผิดพลาดใดยังคงอยู่ คุณสามารถถามคำถามบางอย่างเกี่ยวกับเรื่องนี้ใน StackOverflow ;-) คำถามนี้อาจจะช่วยให้คุณเช่นกัน: stackoverflow.com/questions/34450131/...
Thierry Templier

1
ตั้งแต่ Angular 2 RC 0 สิ่งนี้ไม่จำเป็นอีกต่อไป
Onur Yıldırım

3
@ OnurYıldırımโดยใช้ rc.4 ยังจำเป็นต้องมีการนำเข้านี้เว้นแต่ว่าฉันกำลังทำอะไรผิด
โจเซฟกาเบรียล

18
โปรดอย่าใช้ 'นำเข้า' rxjs / Rx ';' เพราะมันนำเข้าทุกอย่างและ rxjs มีแนวโน้มที่จะค่อนข้างใหญ่ นำเข้าโอเปอเรเตอร์หนึ่งต่อหนึ่งตามที่คุณต้องการ
Drag0

1
เชิงมุม 2 พร้อม rxjs: 5.0.0-beta.12 ที่นี่ และฉันยังต้องimport 'rxjs/add/operator/do'... ในขณะที่เราไม่ต้องทำสิ่งนี้.map()อีกต่อไป แต่สิ่งนี้ช่วยให้.do()กรณีของฉันรู้ว่าฉันต้องนำเข้ามันโดยเฉพาะ ขอบคุณ! โหวตขึ้นหนึ่งรายการจากฉัน :)
MrCroft

82

มีเพียงบางพื้นหลัง ... คู่มือ dev การสื่อสารเซิร์ฟเวอร์ที่เพิ่งสร้างเสร็จ(สุดท้าย) กล่าวถึง / กล่าวถึง / อธิบายสิ่งนี้:

ไลบรารี RxJS ค่อนข้างใหญ่ ขนาดมีความสำคัญเมื่อเราสร้างแอปพลิเคชันที่ใช้งานจริงและปรับใช้กับอุปกรณ์มือถือ เราควรรวมเฉพาะคุณสมบัติที่เราต้องการจริงๆ

ดังนั้นเชิงมุม exposes รุ่นปล้นลงของObservableในrxjs/Observableโมดูลรุ่นที่ขาดเกือบทุกผู้ประกอบการรวมทั้งคนที่เราต้องการที่จะใช้ที่นี่เช่นที่mapวิธีการ

มันขึ้นอยู่กับเราที่จะเพิ่มผู้ประกอบการที่เราต้องการ เราสามารถเพิ่มผู้ดำเนินการแต่ละคนทีละคนจนกว่าเราจะมีการใช้งานการสังเกตที่กำหนดเองปรับตามความต้องการของเราอย่างแม่นยำ

ดังนั้นตามที่ @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ผู้ประกอบการจากรหัสที่จับกระแสสังเกต แต่ล้มเหลวที่จะลบคำสั่งนำเข้าที่สอดคล้องกันรหัสที่ใช้ยังคงเป็นส่วนหนึ่งของmapObservable.prototype

เมื่อผู้รวบรวมพยายามกำจัดรหัสที่ไม่ได้ใช้ ( aka tree shaking ) พวกเขาอาจตัดสินใจที่จะเก็บรหัสของ mapโอเปอเรเตอร์ใน Observable แม้ว่าจะไม่ได้ใช้ในแอปพลิเคชันก็ตาม

โซลูชัน -Pipeable operators

Pipeableผู้ประกอบการที่มีฟังก์ชั่นที่บริสุทธิ์และไม่ได้แพทช์สังเกต คุณสามารถนำเข้าโอเปอเรเตอร์โดยใช้ไวยากรณ์การอิมพอร์ต 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';

ใช้วิธีการนี้ตอนนี้ในการสร้างของคุณมันจะรวมเฉพาะผู้ประกอบการใช้ (แผนที่ในกรณีนี้) ก่อนหน้านี้มันรวมถึงผู้ประกอบการทั้งหมดจากห้องสมุด 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 () และ. สมัครสมาชิก () ได้อย่างง่ายดาย

หากคุณกำลังใช้ Angular เวอร์ชัน 2 ดังนั้นบรรทัดต่อไปนี้ควรใช้งานได้ดี:

import 'rxjs/add/operator/map';

หรือ

import 'rxjs/add/operators/map';

หากคุณยังคงพบปัญหาคุณจะต้อง:

import 'rxjs/Rx';

ฉันไม่ต้องการให้คุณใช้มันโดยตรง bcoz เพิ่มเวลาในการโหลดเนื่องจากมีตัวดำเนินการจำนวนมากในนั้น (มีประโยชน์และไม่มีประโยชน์) ซึ่งไม่ใช่แนวปฏิบัติที่ดีตามบรรทัดฐานอุตสาหกรรมดังนั้นควรตรวจสอบให้แน่ใจ คุณลองใช้สายการนำเข้าที่กล่าวถึงข้างต้นก่อนและหากไม่สามารถใช้งานได้คุณควรใช้ rxjs / Rx


3

ฉันมีทางออกของปัญหานี้

ติดตั้งแพ็คเกจนี้:

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

จากนั้นนำเข้าห้องสมุดนี้

import 'rxjs/add/operator/map'

ในที่สุดก็เริ่มโครงการอิออนของคุณแล้ว

ionic serve -l

3

รุ่นเชิงมุม 6 "0.6.8" rxjs รุ่น 6 "^ 6.0.0"

วิธีนี้ใช้สำหรับ:

  "@angular-devkit/core": "0.6.8",
  "rxjs": "^6.0.0"

ตามที่เราทุกคนรู้ว่ามีการพัฒนาเชิงมุมทุกวันดังนั้นจึงมีการเปลี่ยนแปลงมากมายทุกวันและการแก้ปัญหานี้สำหรับเชิงมุม 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';

ที่สามคุณต้องนำเข้าฟังก์ชั่นแผนที่จาก:

import { map } from 'rxjs/operators';

คุณต้องใช้แผนที่ในท่อเหมือนตัวอย่างนี้:

 constructor(public http:Http){  }

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

มันใช้งานได้โชคดีอย่างสมบูรณ์แบบ!


2

แผนที่ที่คุณใช้ที่นี่ไม่ได้เป็น.map()ใน javascript, มันเป็นฟังก์ชั่นแผนที่ Rxjs ซึ่งทำงานเกี่ยวกับObservablesในเชิงมุม ...

ดังนั้นในกรณีนี้คุณต้องนำเข้าถ้าคุณต้องการใช้แผนที่กับข้อมูลผล ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> ใช้ฟังก์ชันโครงการที่กำหนดให้กับแต่ละค่าที่ปล่อยออกมาโดย Observable ต้นทางและปล่อยค่าผลลัพธ์ที่เป็น Observable

ดังนั้นเพียงนำเข้าเช่นนี้

import 'rxjs/add/operator/map';

1

เนื่องจากบริการHttpในangular2ส่งคืนชนิดสังเกตได้จากไดเรกทอรีการติดตั้ง Angular2 ของคุณ ('node_modules' ในกรณีของฉัน) เราจำเป็นต้องนำเข้าฟังก์ชั่นแผนที่ของ Observable ในส่วนประกอบของคุณโดยใช้บริการhttpเช่น:

import 'rxjs/add/operator/map';


1

เพียงเพิ่มบรรทัดในไฟล์ของคุณ

นำเข้า 'rxjs / Rx';

มันจะนำเข้าพวงของการอ้างอิงทดสอบในเชิงมุม 5


0

จริงอยู่ RxJs ได้แยกตัวดำเนินการแผนที่ออกเป็นโมดูลแยกต่างหากและตอนนี้คุณต้องอธิบายการนำเข้ามันเหมือนตัวดำเนินการอื่น

import rxjs/add/operator/map;

และคุณจะสบายดี




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

นำเข้า {map} จาก 'rxjs / โอเปอเรเตอร์';

มันใช้งานได้สำหรับฉันในเชิงมุม 8


0

บวกกับสิ่งที่ @ 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.