17
votes

Hi I'm trying to follow a tutorial on angular but the tutorial was made in September. I believe the person used angular-cli 1.3.2. I'm not sure which version of rxjs he was using. I'm using angular cli 6.0.0 and angular 6 with rxjs 6.1.0.

I am running into a problem where calling .map on observable is not found. ERROR in xxx/xxx/dataService.ts(19,14): error TS2339: Property 'map' does not exist on type 'Observable<Object>'. I looked into the Observable class and I don't see a function called map.

Is there a new way in angular 6 or rxjs to achieve what the tutorial is trying to do?

Here is my .ts file:

import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { map } from 'rxjs/operators';

@Injectable()
export class DataService {

    constructor(private http: HttpClient) {

    }

    public products = [

    ];

    loadProducts() {
        return this.http.get("/api/products")
            .map((data: any[]) => {
                this.products = data;
                return true;
            });
    }
}

This is the output from ng --version

λ ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 6.0.0
Node: 8.11.1
OS: win32 x64
Angular: 6.0.0
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.0
@angular-devkit/build-angular     0.6.0
@angular-devkit/build-optimizer   0.6.0
@angular-devkit/core              0.6.0
@angular-devkit/schematics        0.6.0 (cli-only)
@ngtools/webpack                  6.0.0
@schematics/angular               0.6.0 (cli-only)
@schematics/update                0.6.0 (cli-only)
rxjs                              6.1.0
typescript                        2.7.2
webpack                           4.6.0

I did a little digging and in my node_modules/rxjs/observable folder there is no map.* file

λ ls -R rxjs\observable
'rxjs\observable':
ArrayLikeObservable.d.ts            IfObservable.d.ts             combineLatest.d.ts       if.js.map
ArrayLikeObservable.js              IfObservable.js               combineLatest.js         interval.d.ts
ArrayLikeObservable.js.map          IfObservable.js.map           combineLatest.js.map     interval.js
ArrayObservable.d.ts                IntervalObservable.d.ts       concat.d.ts              interval.js.map
ArrayObservable.js                  IntervalObservable.js         concat.js                merge.d.ts
ArrayObservable.js.map              IntervalObservable.js.map     concat.js.map            merge.js
BoundCallbackObservable.d.ts        IteratorObservable.d.ts       defer.d.ts               merge.js.map
BoundCallbackObservable.js          IteratorObservable.js         defer.js                 never.d.ts
BoundCallbackObservable.js.map      IteratorObservable.js.map     defer.js.map             never.js
BoundNodeCallbackObservable.d.ts    NeverObservable.d.ts          dom/                     never.js.map
BoundNodeCallbackObservable.js      NeverObservable.js            empty.d.ts               of.d.ts
BoundNodeCallbackObservable.js.map  NeverObservable.js.map        empty.js                 of.js
ConnectableObservable.d.ts          PairsObservable.d.ts          empty.js.map             of.js.map
ConnectableObservable.js            PairsObservable.js            forkJoin.d.ts            onErrorResumeNext.d.ts
ConnectableObservable.js.map        PairsObservable.js.map        forkJoin.js              onErrorResumeNext.js
DeferObservable.d.ts                PromiseObservable.d.ts        forkJoin.js.map          onErrorResumeNext.js.map DeferObservable.js                  PromiseObservable.js          from.d.ts                pairs.d.ts
DeferObservable.js.map              PromiseObservable.js.map      from.js                  pairs.js
EmptyObservable.d.ts                RangeObservable.d.ts          from.js.map              pairs.js.map
EmptyObservable.js                  RangeObservable.js            fromArray.d.ts           race.d.ts
EmptyObservable.js.map              RangeObservable.js.map        fromArray.js             race.js
ErrorObservable.d.ts                ScalarObservable.d.ts         fromArray.js.map         race.js.map
ErrorObservable.js                  ScalarObservable.js           fromEvent.d.ts           range.d.ts
ErrorObservable.js.map              ScalarObservable.js.map       fromEvent.js             range.js
ForkJoinObservable.d.ts             SubscribeOnObservable.d.ts    fromEvent.js.map         range.js.map
ForkJoinObservable.js               SubscribeOnObservable.js      fromEventPattern.d.ts    throw.d.ts
ForkJoinObservable.js.map           SubscribeOnObservable.js.map  fromEventPattern.js      throw.js
FromEventObservable.d.ts            TimerObservable.d.ts          fromEventPattern.js.map  throw.js.map
FromEventObservable.js              TimerObservable.js            fromIterable.d.ts        timer.d.ts
FromEventObservable.js.map          TimerObservable.js.map        fromIterable.js          timer.js
FromEventPatternObservable.d.ts     UsingObservable.d.ts          fromIterable.js.map      timer.js.map
FromEventPatternObservable.js       UsingObservable.js            fromPromise.d.ts         using.d.ts
FromEventPatternObservable.js.map   UsingObservable.js.map        fromPromise.js           using.js
FromObservable.d.ts                 bindCallback.d.ts             fromPromise.js.map       using.js.map
FromObservable.js                   bindCallback.js               generate.d.ts            zip.d.ts
FromObservable.js.map               bindCallback.js.map           generate.js              zip.js
GenerateObservable.d.ts             bindNodeCallback.d.ts         generate.js.map          zip.js.map
GenerateObservable.js               bindNodeCallback.js           if.d.ts
GenerateObservable.js.map           bindNodeCallback.js.map       if.js

'rxjs\observable/dom':
AjaxObservable.d.ts  AjaxObservable.js.map  WebSocketSubject.js      ajax.d.ts  ajax.js.map     webSocket.js
AjaxObservable.js    WebSocketSubject.d.ts  WebSocketSubject.js.map  ajax.js    webSocket.d.ts  webSocket.js.map
7
This is my first time trying to learn angular and using rxjs and your link helped a lot. Thanks!Jonathan
The link in the comment above needs to be read and bookmarked by anyone migrating to rxjs 6. The information therein is quite valuable!!R. Richards
Document is no more available :(Leonardo Minati

7 Answers

27
votes

In rxjs@6 you can use from as standalone function:

import { from } from 'rxjs';

See also migration to rxjs6 guide

https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md#import-paths

UPDATE

You need to switch to pipe syntax, make sure you import all operators used from rxjs/operators. For example:

import { map, filter, catchError, mergeMap } from 'rxjs/operators';

DOCUMENTATION

17
votes

pipe is a method on Observable which is used for composing operators

Here is the way how you can use the new method pipe() in Version 6:

loadProducts() {
    return this.http.get("/api/products").
        pipe(
           map((data: any[]) => {
             this.products = data;
             return true;
           }), catchError( error => {
             return throwError( 'Something went wrong!' )
           });
        )
}

Keep in mind that with Version 6 you should now use catchError and throwError instead of:catch and throw. Here is the correct import with Version 6:

import { Observable, of, throwError, ...} from "rxjs"

import { map, catchError, ...} from "rxjs/operatros"

6
votes

You have to change to pipe syntax:

import { Http  } from '@angular/http';
import { Injectable } from '@angular/core';
import {map, catchError} from "rxjs/operators";

import { Observable, throwError } from 'rxjs';

list():Observable<any>{
    return this.http.get(this.url)
    .pipe(
      map((e:Response)=> e.json()),
      catchError((e:Response)=> throwError(e))
    );
  }
2
votes

i was facing the same problem. lets change the way to import map. use the code which i have written below

import { map } from "rxjs/operators";

then use pipe with map. see the example for better understanding

import {Http,Headers,Response} from '@angular/http';
import { map } from "rxjs/operators";


@Injectable({
  providedIn: 'root'
})
export class ContactServiceService {

  constructor(private http:Http) { }

  getContactList(){
    return this.http.get('http://localhost:3000/contact')
    .pipe(map(res => res.json()));
  }

}

0
votes

The Angular new version actually does not support .map. A few changes have been done in the new angular version. You can check on these by visiting the angular website, but here is a solution of these problems; run these commands in cmd destination of your project:

 npm install --save rxjs-compat

and enjoy with old technique, but don't forget to add these lines in shared service:

import { Observable, Subject } from 'rxjs';
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch';
0
votes

For some obscure reason rxjs-compat sometimes doesn't get picked up automatically, you can import it yourself, in polyfills.ts for example:

import 'rxjs-compat';

0
votes

In Angular 6x with rxjs 6.3.3 you can do this. In the file(app.component.ts)

import { Component } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError, retry } from 'rxjs/operators';

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
})

export class AppComponent {    

  _url = 'http://...';
  constructor( private http: HttpClient ) { }
  articles: Observable<any>;

  // Method to get info
  getAPIRest() {       
    const params = new HttpParams().set('parameter', 'value');
    const headers = new HttpHeaders().set('Autorization', 'auth-token');
    this.articles = this.http.get(this._url + '/articles', { params, headers })
             .pipe( retry(3),
                    map((data => data),
                    catchError(err => throwError(err))));
  }

}