Http.request () से अपवाद को सही तरीके से कैसे पकड़ें?


132

मेरे कोड का हिस्सा:

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() ब्राउज़र के कंसोल में अपवाद उत्पन्न करता है:

मूल अपवाद: TypeError: this.http.request (...)। Map (...)। Catch एक फ़ंक्शन नहीं है।

जवाबों:


213

शायद आप इसे अपने आयातों में जोड़ने का प्रयास कर सकते हैं:

import 'rxjs/add/operator/catch';

आप भी कर सकते हैं:

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

प्रति टिप्पणी:

अपवाद: TypeError: Observable_1.Observable.throw एक फ़ंक्शन नहीं है

इसी तरह, उसके लिए, आप उपयोग कर सकते हैं:

import 'rxjs/add/observable/throw';

2
मदद के लिए धन्यवाद, यह काम करता है। उसके बाद मुझे throw()फंक्शन को लेकर भी यही समस्या है। मैंने import 'rxjs/Rx';इसके बजाय इस लाइन को जोड़ा । अब सभी ऑपरेटर ठीक से काम करते हैं।
एमएनवी

क्या आपने यह देखने के लिए एक त्रुटि का अनुकरण किया कि क्या .catchवास्तव में काम करता है? यह .subscribe() सुनिश्चित करने के लिए काम करता है।
acdcjunior

1
हां, दूसरी समस्या थी EXCEPTION: TypeError: Observable_1.Observable.throw is not a function। यह @MattScarpino जवाब के साथ या इस प्लंकर से मनेर में तय किया जा सकता है जैसा कि मैंने ऊपर कहा था: angular.io/resources/live-examples/server-communication/ts/…
mnv

16
बस आयात फेंक भी: import 'rxjs/add/observable/throw';और सब कुछ आयात नहीं करते, यह बहुत बड़ा है।
22

महान समाधान ,, बहुत उपयोगी है, मैं (गलती) जोड़ सकते हैं प्रकार प्रतिक्रिया की है
मोहम्मद स्वेज

77

HttpClientModule और RxJS v5.5.x का उपयोग करने के लिए नई सेवा अपडेट की गई :

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

पुरानी सेवा, जिसमें उपयोग किए गए HttpModule का उपयोग किया गया है:

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

मैं डिबगिंग के लिए .do()( अब.tap() ) का उपयोग करता हूं ।

जब सर्वर त्रुटि होती है, तो मैं जिस सर्वर (लाइट-सर्वर) का उपयोग कर रहा हूं उससे प्राप्त होने bodyवाली Responseवस्तु में सिर्फ पाठ होता है, इसलिए इसका कारण मैं err.text()इसके बजाय ऊपर का उपयोग करता हूं err.json().error। आपको अपने सर्वर के लिए उस लाइन को समायोजित करने की आवश्यकता हो सकती है।

यदि res.json()कोई त्रुटि उठाता है क्योंकि यह JSON डेटा को पार्स नहीं कर सकता है, तो _serverErrorउसे Responseऑब्जेक्ट नहीं मिलेगा , इसलिए instanceofचेक का कारण ।

इसमें plunker, त्रुटि उत्पन्न urlकरने के ./data/data.junkलिए परिवर्तित करें ।


या तो सेवा के उपयोगकर्ताओं के पास कोड होना चाहिए जो त्रुटि को संभाल सकता है:

@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

इसे करने बहुत सारे तरीके हैं। दोनों बहुत सरल हैं। प्रत्येक उदाहरण महान काम करता है। आप इसे अपनी परियोजना में कॉपी कर सकते हैं और इसका परीक्षण कर सकते हैं।

पहला तरीका बेहतर है, दूसरा थोड़ा पुराना है, लेकिन अब तक यह भी काम करता है।

1) समाधान 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) समाधान 2. यह पुराना तरीका है लेकिन फिर भी काम करता है।

// 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 फ़ंक्शन को विशेष रूप से आयात करने की आवश्यकता है। ऐसा करने का एक आसान तरीका अपनी सभी विशेषताओं को आयात करना हैimport * as Rx from "rxjs/Rx"

तब के Observableरूप में वर्ग का उपयोग सुनिश्चित करें Rx.Observable


15
Rxjs बहुत बड़ी फ़ाइल है, यदि आप इसे आयात करते हैं तो यह आपके लोडिंग समय को
बढ़ा देगा

यदि आपको केवल एक या दो ऑपरेटरों की आवश्यकता है, तो आपको Rxjs से सब कुछ आयात नहीं करना चाहिए।
मार्सेल-के

-4

कोणीय 4 उपयोग के नवीनतम संस्करण में

import { Observable } from 'rxjs/Rx'

यह सभी आवश्यक चीजों को आयात करेगा।


20
ऐसा मत करो, यह सभी Rxjs आयात करेगा।
मार्सेल-के

और इसलिए बंडल आकार में वृद्धि होगी!
तुषार वलज़ादे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.