Angular HTTP Error Empty Untyped Response

时间:2017-09-08 18:17:27

标签: angular typescript error-handling promise jhipster

我有一个进行HTTP调用的Angular / JHipster应用程序。我想在Observable订阅中进行错误处理。

但是,第一次调用错误处理程序时,err对象不是响应,而是原始{} Object。所有后续错误处理程序调用都具有有效的Response

为什么会发生这种情况,我该如何解决?

MyComponent.ts:

handleClickPost() {
    this.myService.doPost(this.body)
    .subscribe(
        (res: Response) => {
            this.responseOk = true;
        },
        (err: Response) => {
            // This is a HACK!
            // For some reason, the first time this error handler is invoked (after page load),
            // the response body is empty here and serializes to "{}".
            if (JSON.stringify(err) === '{}') {
                // first request always reaches here... WHY?
                this.handleClickPost(); // NB: workaround
                // err.json(); // results in null "method not found" error
            } else {
                // second request always reaches here... WHY?
                // (I want all requests to go here with a valid 'Response' object)
                this.showRequestFailed = true;
                this.errorResponse = err.json();
            }
        }
    );
}

MyService.ts:

doPost(body): Observable<Response> {
    return this.http.post(this.resourceUrl, body);
}

我的伪劣解决方法是在第一次空体失败后再次调用该方法,以获得一个键入的Response

注意:Angular 2和Angular 4都会出现这种情况。

2 个答案:

答案 0 :(得分:3)

首先,您必须检查几件事情,以确保您的设置正确无误。

  1. 检查服务器端是否在第一次请求时发送正确的JSON编码响应,即响应是否正确序列化。

  2. 如果要将json数据发布到服务器,请检查POST请求this.body的有效负载是否已转换为json字符串。你应该用 如果您要发送json数据,请在发送请求之前JSON.stringify(this.body)

  3. 你应该在你的post()方法中使用map()/ catch()来实际映射响应并捕获实际错误。

  4. 所以你的代码应该如下所示

    <强> MyService.ts:

    doPost(body:any): Observable<Response> {
       let payload = JSON.stringify(body); // Stringify payload if you are using JSON data
       let headers      = new Headers({ 'Content-Type': 'application/json' }); // ... Set content type to JSON for json request
       let options      = new RequestOptions({ headers: headers }); // Create a request option
       return this.http.post(this.resourceUrl, payload,options)
                            .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
                            .catch((error:any) => Observable.throw(error.json().error || 'Server error')); //...errors if any;
    }
    

    <强> MyComponent.ts:

    handleClickPost() {
        this.myService.doPost(this.body)
        .subscribe(
            (res: any) => {
                this.responseOk = true;
            },
            (err: any) => {
                // Log errors if any
                console.log(err);
               }
            }
        );
    }
    

    或者您可以为catch()方法创建单独的错误处理程序,如下所示

    private handleError(error: any) {
          let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
           console.log(errMsg); // log to console instead
            return Observable.throw(errMsg);
        }
    

    并在服务类中以.catch(this.handleError)的方式使用它。

答案 1 :(得分:1)

似乎是预检Http OPTIONS请求的问题。您是否验证了响应类型。

如果是这个问题,您可以通过修改内容标题来避免预检请求。

   $http.defaults.headers.post["Content-Type"] = "text/plain"

在此处阅读更多内容:Why am I getting an OPTIONS request instead of a GET request?