HTTP GET góc với lỗi TypeScript http.get (Hoài) .map không phải là một hàm trong [null]


334

Tôi có một vấn đề với HTTP trong Angular.

Tôi chỉ muốn GETmột JSONdanh sách và hiển thị nó trong chế độ xem.

Lớp dịch vụ

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

Và trong HallListComponenttôi gọi getHallsphương thức từ dịch vụ:

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

Tuy nhiên, tôi có một ngoại lệ:

LoạiError: this.http.get (...). Map không phải là một chức năng trong [null]

hội trường-trung tâm

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

ứng dụng

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

Không http.get trả lại một lời hứa?
bmm6o

1
@ bmm6o HttpDịch vụ mới trả về có thể quan sát được
Brocco

1
Tôi gặp phải một vấn đề gần như giống hệt nhau, cố gắng chuyển một dự án từ Angular2 beta-17 sang bản phát hành cuối cùng. Vấn đề đối với tôi là IDE của tôi, sử dụng VS 2015, Cập nhật 3. Phần mở rộng dịch vụ ngôn ngữ TypeScript vẫn còn 1.8.36, trong khi hướng dẫn khởi động nhanh ng2 (khi tôi viết bài này) đang sử dụng "typescript": "^2.0.2". Nâng cấp lang TS. dịch vụ thông qua Tiện ích mở rộng và Cập nhật đã giúp tôi. Trong khi bản cập nhật đó đang được cài đặt, tôi đã xem qua câu trả lời SO này , kết thúc với cùng một kết luận.
Eric thuê

Đối với phpstorm / webstorm, việc cập nhật phiên bản bản thảo với thư viện của dự án của tôi cũng giải quyết được vấn đề. Tôi đã làm theo các bước của câu trả lời SO này: stackoverflow.com/a/31608934/1291428
Sebas

Câu trả lời:


538

Tôi nghĩ rằng bạn cần phải nhập cái này:

import 'rxjs/add/operator/map'

Hay nói chung hơn nếu bạn muốn có nhiều phương pháp hơn để quan sát. CẢNH BÁO: Điều này sẽ nhập tất cả hơn 50 toán tử và thêm chúng vào ứng dụng của bạn, do đó ảnh hưởng đến kích thước gói và thời gian tải của bạn.

import 'rxjs/Rx';

Xem vấn đề này để biết thêm chi tiết.


1
Những lỗi nào vẫn còn? Bạn có thể hỏi một số câu hỏi cụ thể liên quan đến vấn đề này trên stackoverflow ;-) Câu hỏi này có lẽ cũng có thể giúp bạn: stackoverflow.com/questions 432450131 / Lỗi .
Thierry Templier

1
Kể từ Angular 2 RC 0, điều này không còn cần thiết nữa.
Onur Yıldırım

3
@ OnurYıldırım, sử dụng RC.4, việc nhập này vẫn được yêu cầu, trừ khi tôi làm sai.
Joseph Gabriel

18
Vui lòng không sử dụng 'nhập' rxjs / Rx ';' bởi vì nó nhập khẩu mọi thứ và rxjs có xu hướng khá lớn. Nhập toán tử từng cái một khi bạn cần chúng.
Drag0

1
Góc 2 với rxjs: 5.0.0-beta.12 tại đây. Và tôi vẫn phải import 'rxjs/add/operator/do'... Trong khi chúng ta không phải làm điều này .map()nữa. Nhưng điều này đã giúp .do()trường hợp của tôi , để nhận ra tôi đặc biệt cần phải nhập nó. Cảm ơn bạn! Một phiếu bầu từ tôi :)
MrCroft

82

Chỉ là một số nền tảng ... Hướng dẫn dành cho nhà phát triển Server Communication mới được thảo luận (cuối cùng) thảo luận / đề cập / giải thích điều này:

Thư viện RxJS khá lớn. Kích thước quan trọng khi chúng tôi xây dựng một ứng dụng sản xuất và triển khai nó cho các thiết bị di động. Chúng ta chỉ nên bao gồm những tính năng mà chúng ta thực sự cần.

Theo đó, Angular trưng bày một phiên bản rút gọn Observabletrong rxjs/Observablemô-đun, một phiên bản thiếu gần như tất cả các toán tử bao gồm cả các toán tử mà chúng tôi muốn sử dụng ở đây, chẳng hạn như mapphương thức.

Tùy thuộc vào chúng tôi để thêm các toán tử mà chúng tôi cần. Chúng tôi có thể thêm từng toán tử, từng cái một, cho đến khi chúng tôi có một triển khai Có thể quan sát tùy chỉnh được điều chỉnh chính xác theo yêu cầu của chúng tôi.

Vì vậy, như @Thierry đã trả lời, chúng ta có thể lấy các toán tử mà chúng ta cần:

import 'rxjs/add/operator/map';
import 'rxjs/operator/delay';
import 'rxjs/operator/mergeMap';
import 'rxjs/operator/switchMap';

Hoặc, nếu chúng ta lười biếng, chúng ta có thể tập hợp đầy đủ các toán tử. CẢNH BÁO: điều này sẽ thêm tất cả hơn 50 toán tử vào gói ứng dụng của bạn và sẽ ảnh hưởng đến thời gian tải

import 'rxjs/Rx';

2
nhập 'rxjs / Rx'; ồ và tất cả tóc của tôi kéo ngay lập tức biến mất. Tôi không thể tin rằng điều này không được in trên toàn thế giới cho Rxjs / Angular2. cảm ơn!!!
JimB

Nhưng nó thường không bị mất, theo mặc định, đây là một mục nhập trong danh sách đen. Tạo một dự án CLI góc cạnh mới, bạn sẽ thấy. Bản thân tôi yêu sự tiện lợi nhưng hội nghị ở những nơi tôi làm việc ở NYC không phải để làm điều đó.
Tim Consolazio

21

Từ rxjs 5,5 trở đi, bạn có thể sử dụng pipeable nhà khai thác

import { map } from 'rxjs/operators';

Có chuyện gì với import 'rxjs/add/operator/map';

Khi chúng ta sử dụng phương pháp này, maptoán tử sẽ được vá observable.prototype và trở thành một phần của đối tượng này.

Nếu sau này, bạn quyết định xóa maptoán tử khỏi mã xử lý luồng có thể quan sát được nhưng không xóa câu lệnh nhập tương ứng, mã thực hiện mapvẫn là một phần của Observable.prototype.

Khi các trình đóng gói cố gắng loại bỏ mã không được sử dụng ( aka tree shaking ), họ có thể quyết định giữ mã của maptoán tử trong Observable mặc dù nó không được sử dụng trong ứng dụng.

Giải pháp -Pipeable operators

Toán tử có thể điều chỉnh được là các hàm thuần túy và không vá lỗi có thể quan sát được . Bạn có thể nhập các toán tử bằng cú pháp nhập ES6 import { map } from "rxjs/operators"và sau đó bọc chúng thành một hàm pipe()có số lượng tham số thay đổi, tức là các toán tử có thể xâu chuỗi .

Một cái gì đó như thế này:

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

16

Với Angular 5, nhập khẩu RxJS được cải thiện.

Thay vì

import 'rxjs/add/operator/map';

Bây giờ chúng ta có thể

import { map } from 'rxjs/operators';

Sử dụng phương pháp này, bây giờ trong bản dựng của bạn, nó sẽ chỉ bao gồm các toán tử đã sử dụng (bản đồ trong trường hợp này), trước đó nó bao gồm tất cả các toán tử từ thư viện rxjs. kiểm tra liên kết dưới đây để biết thêm chi tiết. loiane.com/2017/08/angular-rxjs-imports
Hiren Shah

13

Sử dụng Observable.subscribetrực tiếp nên làm việc.

@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
Đây không phải là một cách tiếp cận rất hiệu quả. Chẳng hạn, nếu có nhiều người đăng ký, mỗi người sẽ phải chạy bản đồ trên dữ liệu, thay vì chỉ thực hiện một lần trong dịch vụ. Tôi nghĩ OP đã có cách tiếp cận đúng, chỉ cần không có mô-đun phù hợp được tải để sử dụng nó.
Evan Plaice

3

Đối với phiên bản Angular 5 trở lên, dòng nhập được cập nhật trông như sau:

import { map } from 'rxjs/operators';

HOẶC LÀ

import { map } from 'rxjs/operators';

Ngoài ra các phiên bản này hoàn toàn hỗ trợ các nhà khai thác Pipable để bạn có thể dễ dàng sử dụng .pipe () và .subscribe ().

Nếu bạn đang sử dụng Angular phiên bản 2, thì dòng sau sẽ hoạt động hoàn toàn tốt:

import 'rxjs/add/operator/map';

HOẶC LÀ

import 'rxjs/add/operators/map';

Nếu bạn vẫn gặp phải một vấn đề thì bạn phải đi với:

import 'rxjs/Rx';

Tôi sẽ không thích bạn sử dụng nó trực tiếp bởi vì nó tăng thời gian tải, vì nó có một số lượng lớn các toán tử trong đó (những công cụ hữu ích và không hữu ích) không phải là một thông lệ tốt theo các quy tắc của ngành, vì vậy hãy đảm bảo bạn thử sử dụng các dòng nhập được đề cập ở trên trước và nếu nó không hoạt động thì bạn nên tìm rxjs / Rx


3

Tôi có một giải pháp cho vấn đề này

Cài đặt gói này:

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

sau đó nhập thư viện này

import 'rxjs/add/operator/map'

cuối cùng khởi động lại dự án ion của bạn

ionic serve -l

3

Phiên bản góc 6 "0.6.8" rxjs phiên bản 6 "^ 6.0.0"

giải pháp này là dành cho:

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

vì tất cả chúng ta đều biết angular đang được phát triển mỗi ngày nên có rất nhiều thay đổi mỗi ngày và giải pháp này dành cho angular 6 và rxjs 6
trước tiên để làm việc với http yo nên nhập nó từ: sau tất cả, bạn phải khai báo httpModule trong ứng dụng. mô-đun

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

và bạn phải thêm HttpModule vào Ngmodule -> nhập

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

Thứ hai để làm việc với bản đồ, trước tiên bạn nên nhập ống:

import { pipe } from 'rxjs';

thứ ba bạn cần nhập chức năng bản đồ từ:

import { map } from 'rxjs/operators';

bạn phải sử dụng bản đồ bên trong đường ống như ví dụ này:

 constructor(public http:Http){  }

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

hoạt động hoàn toàn may mắn!


2

Các bản đồ bạn sử dụng ở đây, không phải là .map()trong javascript, nó Rxjs chức năng bản đồ mà làm việc trênObservables trong góc ...

Vì vậy, trong trường hợp đó, bạn cần nhập nó nếu bạn muốn sử dụng bản đồ trên dữ liệu kết quả ...

map(project: function(value: T, index: number): R, thisArg: any): Observable<R> Áp dụng một hàm dự án nhất định cho từng giá trị được phát ra từ nguồn có thể quan sát được và phát ra các giá trị kết quả dưới dạng có thể quan sát được.

Vì vậy, chỉ cần nhập nó như thế này:

import 'rxjs/add/operator/map';

1

Vì dịch vụ http trong angular2 trả về loại Có thể quan sát được , Từ thư mục cài đặt Angular2 của bạn ('node_modules' trong trường hợp của tôi), chúng tôi cần nhập chức năng bản đồ của Đài quan sát trong thành phần của bạn bằng dịch vụ http , như:

import 'rxjs/add/operator/map';


1

Chỉ cần thêm dòng trong tập tin của bạn,

nhập 'rxjs / Rx';

Nó sẽ nhập một loạt các phụ thuộc. Được kiểm tra trong góc 5


0

Đúng, RxJs đã tách toán tử bản đồ của nó trong một mô-đun riêng biệt và bây giờ bạn cần khám phá nhập nó như bất kỳ toán tử nào khác.

import rxjs/add/operator/map;

và bạn sẽ ổn thôi


0

Nhập khẩu toàn cầu là an toàn để đi với.

nhập 'rxjs / Rx';


0
import 'rxjs/add/operator/map';

sẽ giải quyết vấn đề của bạn

Tôi đã thử nghiệm nó ở góc 5.2.0 và rxjs 5.5.2


0

điều này xảy ra bởi vì bạn đang sử dụng rxjs và trong hàm rxjs không tĩnh, điều đó có nghĩa là bạn không thể gọi chúng trực tiếp, bạn phải gọi các phương thức bên trong đường ống và nhập hàm đó từ thư viện rxjs

Nhưng nếu bạn đang sử dụng rxjs-compat thì bạn chỉ cần nhập các toán tử rxjs-compat


0

Tôi đã thử các lệnh bên dưới và nó được sửa:

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


import 'rxjs/Rx';

Điều đó chỉ để giúp bạn ban đầu làm việc trong rxjs 6 bằng cách thực hiện một số bản vá cho bạn. Nó chỉ là một sửa chữa ngắn hạn và quá trình chuyển đổi rxjs 6 đầy đủ nên được thực hiện.
HankCa


0

Cộng với những gì @ mlc-mlapis nhận xét, bạn đang trộn các toán tử có thể sử dụng được và phương pháp vá nguyên mẫu. Sử dụng cái này hay cái khác .

Đối với trường hợp của bạn, nó nên được

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.