Http.request () 'den özel durum nasıl doğru bir şekilde yakalanır?


133

Kodumun bir parçası:

import {Injectable} from 'angular2/core';
import {Http, Headers, Request, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class myClass {

  constructor(protected http: Http) {}

  public myMethod() {
    let request = new Request({
      method: "GET",
      url: "http://my_url"
    });

    return this.http.request(request)
      .map(res => res.json())
      .catch(this.handleError); // Trouble line. 
                                // Without this line code works perfectly.
  }

  public handleError(error: Response) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
  }

}

myMethod() tarayıcı konsolunda istisna oluşturur:

ORİJİNAL İSTİSNA: TypeError: this.http.request (...). Map (...). Catch bir işlev değildir

Yanıtlar:


214

Belki bunu ithalatlarınıza eklemeyi deneyebilirsiniz:

import 'rxjs/add/operator/catch';

Ayrıca şunları da yapabilirsiniz:

return this.http.request(request)
  .map(res => res.json())
  .subscribe(
    data => console.log(data),
    err => console.log(err),
    () => console.log('yay')
  );

Yorum başına:

İSTİSNA: TypeError: Observable_1.Observable.throw bir işlev değildir

Benzer şekilde, bunun için şunları kullanabilirsiniz:

import 'rxjs/add/observable/throw';

2
Yardımın için teşekkürler, işe yarıyor. Bundan sonra throw()işlevle aynı problemim var . Onun import 'rxjs/Rx';yerine bu satırı ekledim . Artık tüm operatörler düzgün çalışıyor.
mnv

.catchGerçekten çalışıp çalışmadığını görmek için bir hatayı simüle ettiniz mi? Yani .subscribe() kesin işler.
acdcjunior

1
Evet, ikinci sorun buydu EXCEPTION: TypeError: Observable_1.Observable.throw is not a function. Yukarıda da belirttiğim gibi bu plunker gelen @MattScarpino cevap veya maner sabit edilebilir: angular.io/resources/live-examples/server-communication/ts/...
MNV

16
Sadece atmayı da içe aktarın: import 'rxjs/add/observable/throw';ve her şeyi içe aktarmayın, bu çok büyük.
dfsq

Harika çözüm, çok faydalı, (err) türünde Yanıt ekleyebilirim
Muhammed Suez

77

HttpClientModule ve RxJS v5.5.x'i kullanmak için güncellenen yeni hizmet :

import { Injectable }                    from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable }                    from 'rxjs/Observable';
import { catchError, tap }               from 'rxjs/operators';
import { SomeClassOrInterface}           from './interfaces';
import 'rxjs/add/observable/throw';

@Injectable() 
export class MyService {
    url = 'http://my_url';
    constructor(private _http:HttpClient) {}
    private handleError(operation: String) {
        return (err: any) => {
            let errMsg = `error in ${operation}() retrieving ${this.url}`;
            console.log(`${errMsg}:`, err)
            if(err instanceof HttpErrorResponse) {
                // you could extract more info about the error if you want, e.g.:
                console.log(`status: ${err.status}, ${err.statusText}`);
                // errMsg = ...
            }
            return Observable.throw(errMsg);
        }
    }
    // public API
    public getData() : Observable<SomeClassOrInterface> {
        // HttpClient.get() returns the body of the response as an untyped JSON object.
        // We specify the type as SomeClassOrInterfaceto get a typed result.
        return this._http.get<SomeClassOrInterface>(this.url)
            .pipe(
                tap(data => console.log('server data:', data)), 
                catchError(this.handleError('getData'))
            );
    }

Kullanımdan kaldırılmış HttpModule kullanan eski hizmet:

import {Injectable}              from 'angular2/core';
import {Http, Response, Request} from 'angular2/http';
import {Observable}              from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
//import 'rxjs/Rx';  // use this line if you want to be lazy, otherwise:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';  // debug
import 'rxjs/add/operator/catch';

@Injectable()
export class MyService {
    constructor(private _http:Http) {}
    private _serverError(err: any) {
        console.log('sever error:', err);  // debug
        if(err instanceof Response) {
          return Observable.throw(err.json().error || 'backend server error');
          // if you're using lite-server, use the following line
          // instead of the line above:
          //return Observable.throw(err.text() || 'backend server error');
        }
        return Observable.throw(err || 'backend server error');
    }
    private _request = new Request({
        method: "GET",
        // change url to "./data/data.junk" to generate an error
        url: "./data/data.json"
    });
    // public API
    public getData() {
        return this._http.request(this._request)
          // modify file data.json to contain invalid JSON to have .json() raise an error
          .map(res => res.json())  // could raise an error if invalid JSON
          .do(data => console.log('server data:', data))  // debug
          .catch(this._serverError);
    }
}

Hata ayıklamak için .do()( şimdi.tap() ) kullanıyorum .

Bir sunucu hatası olduğunda, bodybir Responseben (lite-sunucu) kullanıyorum sunucudan almak nesnenin sadece metin, kullandığım dolayısıyla nedeni içerir err.text()ziyade yukarıda err.json().error. Sunucunuz için bu satırı ayarlamanız gerekebilir.

res.json()JSON verilerini ayrıştıramadığı için bir hata ortaya çıkarırsa , bir nesne _serverErroralamaz Response, dolayısıyla instanceofkontrolün nedeni budur .

Bunu bir hata oluşturmak için olarak plunkerdeğiştirin .url./data/data.junk


Her iki hizmetin kullanıcıları, hatayı işleyebilecek koda sahip olmalıdır:

@Component({
    selector: 'my-app',
    template: '<div>{{data}}</div> 
       <div>{{errorMsg}}</div>`
})
export class AppComponent {
    errorMsg: string;
    constructor(private _myService: MyService ) {}
    ngOnInit() {
        this._myService.getData()
            .subscribe(
                data => this.data = data,
                err  => this.errorMsg = <any>err
            );
    }
}

4

Bunu yapmanın birkaç yolu var. İkisi de çok basit. Örneklerin her biri harika çalışıyor. Bunu projenize kopyalayabilir ve test edebilirsiniz.

İlk yöntem tercih edilir, ikincisi biraz modası geçmiş, ancak şu ana kadar işe yarıyor.

1) Çözüm 1

// File - app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { ProductService } from './product.service';
import { ProductModule } from './product.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [ProductService, ProductModule],
  bootstrap: [AppComponent]
})
export class AppModule { }



// File - product.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

// Importing rxjs
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';
import { catchError, tap } from 'rxjs/operators'; // Important! Be sure to connect operators

// There may be your any object. For example, we will have a product object
import { ProductModule } from './product.module';

@Injectable()
export class ProductService{
    // Initialize the properties.
    constructor(private http: HttpClient, private product: ProductModule){}

    // If there are no errors, then the object will be returned with the product data.
    // And if there are errors, we will get into catchError and catch them.
    getProducts(): Observable<ProductModule[]>{
        const url = 'YOUR URL HERE';
        return this.http.get<ProductModule[]>(url).pipe(
            tap((data: any) => {
                console.log(data);
            }),
            catchError((err) => {
                throw 'Error in source. Details: ' + err; // Use console.log(err) for detail
            })
        );
    }
}

2) Çözüm 2. Eski bir yöntem ama hala çalışıyor.

// File - app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { ProductService } from './product.service';
import { ProductModule } from './product.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule
  ],
  providers: [ProductService, ProductModule],
  bootstrap: [AppComponent]
})
export class AppModule { }



// File - product.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';

// Importing rxjs
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class ProductService{
    // Initialize the properties.
    constructor(private http: Http){}

    // If there are no errors, then the object will be returned with the product data.
    // And if there are errors, we will to into catch section and catch error.
    getProducts(){
        const url = '';
        return this.http.get(url).map(
            (response: Response) => {
                const data = response.json();
                console.log(data);
                return data;
            }
        ).catch(
            (error: Response) => {
                console.log(error);
                return Observable.throw(error);
            }
        );
    }
}

-1

RxJS işlevlerinin özel olarak içe aktarılması gerekir. Bunu yapmanın kolay bir yolu, tüm özellikleriniimport * as Rx from "rxjs/Rx"

Ardından Observablesınıfa olarak eriştiğinizden emin olun Rx.Observable.


15
Rxjs çok büyük bir dosya, eğer tüm özelliklerini içe aktarırsanız yükleme
sürenizi artıracaktır

Yalnızca bir veya iki operatöre ihtiyacınız varsa, her şeyi Rxjs'den içe aktarmamalısınız.
marcel-k

-4

angular4 kullanımının en son sürümünde

import { Observable } from 'rxjs/Rx'

gerekli tüm şeyleri içe aktaracaktır.


20
Bunu yapmayın, tüm Rxj'leri içe aktaracaktır.
marcel-k

Ve böylece paket boyutunun artmasına neden olur!
Tushar Walzade
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.