为了账号安全,请及时绑定邮箱和手机立即绑定

如何从http.request()正确捕获异常?

/ 猿问

如何从http.request()正确捕获异常?

慕婉清6462132 2019-11-11 10:49:04

我的部分代码:


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不是函数


查看完整描述

3 回答

?
偶然的你

有几种方法可以做到这一点。两者都很简单。每个示例都很棒。您可以将其复制到项目中并进行测试。


第一种方法是可取的,第二种方法有些过时,但是到目前为止它仍然可行。


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

            }

        );

    }

}


查看完整回答
反对 回复 2019-11-11
?
慕标琳琳

也许您可以尝试在导入中添加以下内容:


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


查看完整回答
反对 回复 2019-11-11
?
繁星coding

更新了新服务以使用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

            );

    }

}


查看完整回答
反对 回复 2019-11-11

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信