44 votes

La propriété 'do' n'existe pas sur le type 'Observable <IProduct[]> "

Après la mise à niveau vers Angular 6.0 et Rxjs vers 6.0, je reçois l'erreur de compilation suivante:

Property 'do' does not exist on type 'Observable'.

Voici le code:

 import { Observable, of } from 'rxjs';
import 'rxjs/add/operator/do';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import { IProduct } from './product';

@Injectable()
export class ProductService { 
    constructor(
        private product: IProduct)
    {         
    }

    getProduct = () => { 
        return product.products
            // error on next line
            .do(data => console.log('All:' + JSON.stringify(data)))
            .catch(this.handleError);
    }

    private handleError(err: HttpErrorResponse) { 
        console.log(err.message);
        return Observable.throw(err.message);        
    }
}
 

Une idée?

95voto

Le problème n'est pas avec anguleux, mais avec rxjs. rxjs introduit des modifications importantes de rxjs version 6.

Pour obtenir votre code fonctionne à nouveau sans modification de votre code d'installer le paquet suivant:

npm install rxjs-compat@6 --save

Vous devriez alors être en mesure de compiler votre projet. rxjs-compat est destiné à être une solution temporaire si vous avez besoin de mettre à jour votre base de code pour travailler avec la nouvelle version.


Nouveau Chemin D'Importation

Ce que vous devez mettre à jour:

  1. Mise à jour des déclarations d'importation de

    import { Observable } from "rxjs/Observable";

    pour

    import { Observable } from "rxjs";

  2. Mise à jour de votre opérateur importations en provenance de

    import 'rxjs/add/operator/do'

    pour

    import { do } from "rxjs/operators";


Renommé Opérateurs

Certains opérateurs ont également été renommé en raison de conflits de noms avec JavaScript mots réservés. Ils sont

  1. do => tap

  2. catch => catchError

  3. switch => switchAll

  4. finally => finalize


L'Opérateur N'A Pas De Chaînage

Vous aussi ne peut pas la chaîne de vos opérateurs plus vous devez utiliser l' pipe de l'opérateur par exemple

// an operator chain
source
  .map(x => x + x)
  .mergeMap(n => of(n + 1, n + 2)
    .filter(x => x % 1 == 0)
    .scan((acc, x) => acc + x, 0)
  )
  .catch(err => of('error found'))
  .subscribe(printResult);
// must be updated to a pipe flow
source.pipe(
  map(x => x + x),
  mergeMap(n => of(n + 1, n + 2).pipe(
    filter(x => x % 1 == 0),
    scan((acc, x) => acc + x, 0),
  )),
  catchError(err => of('error found')),
).subscribe(printResult);

16voto

paulsm4 Points 39422

J'apprécie Tjaart van der Walt réponse sur la façon de résoudre les "modifications importantes" introduit dans Angulaire/rxjs7++. Mais j'ai toujours rencontré plusieurs problèmes en essayant d'appliquer sa réponse à mon Angulaire de l'intercepteur:

Voici le code mis à jour (les sections qui n'ont pas pu compiler la mention "VIEUX")

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpResponse} from '@angular/common/http';
import {HttpHandler, HttpRequest, HttpErrorResponse} from '@angular/common/http';

/*
  OLD:
  import {Observable} from 'rxjs/Observable';
  import 'rxjs/add/operator/do';
 */
import { Observable } from 'rxjs';
import { of } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';

import { AuthService } from './auth.service';

@Injectable()
export class StockAppInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.authService.authToken) {
      const authReq = req.clone({
        headers: req.headers.set(
          'Authorization',
          this.authService.authToken
        )
      });
      console.log('Making an authorized request');
      req = authReq;
    }
    /*
     * OLD:
     * return next.handle(req)
     *   .do(event => this.handleResponse(req, event),
     *      error => this.handleError(req, error));
     */
    return next.handle(req).pipe(
      tap(
        event => this.handleResponse(req, event),
        error => this.handleError(req, error)
      )
    );
  }


  handleResponse(req: HttpRequest<any>, event) {
    console.log('Handling response for ', req.url, event);
    if (event instanceof HttpResponse) {
      console.log('Request for ', req.url,
          ' Response Status ', event.status,
          ' With body ', event.body);
    }
  }

  handleError(req: HttpRequest<any>, event) {
    console.error('Request for ', req.url,
          ' Response Status ', event.status,
          ' With error ', event.error);
  }
}

Les modifications requises comprennent l'évolution de la import chemins, et la substitution pipe(), tap() et of().

Ce lien est également une bonne ressource pour RxJS6 changements:

https://www.academind.com/learn/javascript/rxjs-6-what-changed/

14voto

Sébastien Helbert Points 1494

Rxjs 6 a introduit quelques modifications importantes et le "faire" de l'opérateur a été remplacé par le "toucher" de l'opérateur (à partir de 'rxjs/internal/operators').

Vous pourriez refactoriser votre code à l'aide de l'opérateur new, ou encore utiliser l'ancien 'faire' de la syntaxe par l'ajout de la rxjs-compat bibliothèque pour la compatibilité descendante (npm install --save rxjs-compat).

Notez qu'avant RxJs 6 vous avez eu à importer le "faire" de l'opérateur :

import 'rxjs/add/operator/do';

Plus de détails ici : Angulaire HTTP GET avec Tapuscrit d'erreur http.obtenir(...).la carte n'est pas une fonction dans [null]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X