Кутовий HTTP GET з помилкою TypeScript http.get (…) .map не є функцією в [null]


334

У мене проблема з HTTP у Angular.

Я просто хочу , щоб 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]

hall-center.com компонент

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послуга повертає спостережуване
Брокко

1
Я зіткнувся з майже однаковою проблемою, намагаючись перенести проект з Angular2 beta-17 до остаточного випуску. Проблемою для мене був мій IDE, хоча за допомогою VS 2015, оновлення 3. Розширення служби мови TypeScript все ще було в роботі 1.8.36, тоді як як посібник з швидкого запуску ng2 (як я це пишу) використовується "typescript": "^2.0.2". Оновлення TS lang. сервіс через розширення та оновлення зробив для мене трюк. Під час встановлення цього оновлення я натрапив на цю відповідь , яка закінчується тим же висновком.
Ерік Лізинг

Для phpstorm / webstorm оновлення версії машинопису з бібліотекою мого проекту також вирішило проблему. Я дотримувався кроків цієї відповіді ТА
Себас

Відповіді:


538

Я думаю, що вам потрібно імпортувати це:

import 'rxjs/add/operator/map'

Або в цілому це, якщо ви хочете мати більше методів спостереження. ПОПЕРЕДЖЕННЯ. Це імпортує всі 50+ операторів і додасть їх у вашу програму, тим самим впливаючи на розмір пакету та час завантаження.

import 'rxjs/Rx';

Докладніше див. У цьому питанні .


1
Які помилки залишаються? Ви можете задати деякі конкретні запитання щодо цього на stackoverflow ;-) Це питання може вам також допомогти: stackoverflow.com/questions/34450131/… .
Тіррі Темплієр

1
Станом на Angular 2 RC 0 це більше не потрібно.
Onur Yıldırım

3
@ OnurYıldırım, використовуючи rc.4, цей імпорт все ще потрібен, якщо я не роблю щось не так.
Джозеф Габріель

18
Будь ласка, не використовуйте 'import' rxjs / Rx ';' тому що він імпортує все, а rxjs, як правило, досить великий. Імпортуйте операторів по одному, як вам потрібно.
Перетягніть

1
Кутовий 2 з rxjs: 5.0.0-beta.12 тут. І мені все одно довелося import 'rxjs/add/operator/do'... Поки нам більше цього не потрібно робити .map(). Але це допомогло моєму .do()випадку зрозуміти, що я спеціально потребую імпорту. Дякую! Один голос від мене :)
MrCroft

82

Лише деякий досвід ... Щойно відрізаний посібник із розробки сервера зв'язку (нарешті) обговорює / згадує / пояснює це:

Бібліотека RxJS досить велика. Розмір має значення, коли ми створюємо виробничий додаток і розгортаємо його на мобільних пристроях. Ми повинні включати лише ті функції, які насправді потрібні.

Відповідно, Кутове виставляє усічену версію 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, побачите. Сам я люблю зручність, але умовами в місцях, де я працюю в Нью-Йорку, є не робити цього.
Тім Консолазіо

21

Від rxjs 5.5 і далі ви можете використовувати оператори, що передаються в дію

import { map } from 'rxjs/operators';

Що не так з import 'rxjs/add/operator/map';

Коли ми використовуємо цей підхід, mapоператор буде виправлений observable.prototype і стане частиною цього об'єкта.

Якщо пізніше ви вирішите видалити mapоператора з коду, який обробляє спостережуваний потік, але не зможете видалити відповідний оператор імпорту, код, який реалізується, 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())
    );
}

16

Завдяки Angular 5 поліпшується імпорт RxJS.

Замість

import 'rxjs/add/operator/map';

Ми можемо зараз

import { map } from 'rxjs/operators';

Використовуючи цей підхід, тепер у вашу збірку він буде включати лише використані оператори (карта в даному випадку), раніше він включав усіх операторів з бібліотеки rxjs. Перевірте нижче посилання для більш детальної інформації. loiane.com/2017/08/angular-rxjs-imports
Шах

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
Це не дуже ефективний підхід. Наприклад, якщо є декілька абонентів, кожному з них доведеться запускати карту даних, а не просто робити це один раз у сервісі. Я думаю, що в ОП був правильний підхід, просто не було завантажено правильний модуль для його використання.
Еван Плейс

3

Для кутових версій 5 і вище оновлена ​​лінія імпорту виглядає так:

import { map } from 'rxjs/operators';

АБО

import { map } from 'rxjs/operators';

Крім того, ці версії повністю підтримують оператори Pipable, щоб ви могли легко використовувати .pipe () та .subscribe ().

Якщо ви використовуєте кутову версію 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

Кутова версія 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, і отримує отримані значення у якості спостерігаються.

Тому просто імпортуйте його так:

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
import 'rxjs/add/operator/map';

вирішить вашу проблему

Я перевірив його в кутових 5.2.0 і rxjs 5.5.2


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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.