我有一个进行HTTP调用的Angular / JHipster应用程序。我想在Observable
订阅中进行错误处理。
但是,第一次调用错误处理程序时,err
对象不是响应,而是原始{}
Object
。所有后续错误处理程序调用都具有有效的Response
。
为什么会发生这种情况,我该如何解决?
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();
}
}
);
}
doPost(body): Observable<Response> {
return this.http.post(this.resourceUrl, body);
}
我的伪劣解决方法是在第一次空体失败后再次调用该方法,以获得一个键入的Response
。
注意:Angular 2和Angular 4都会出现这种情况。
答案 0 :(得分:3)
首先,您必须检查几件事情,以确保您的设置正确无误。
检查服务器端是否在第一次请求时发送正确的JSON编码响应,即响应是否正确序列化。
如果要将json数据发布到服务器,请检查POST请求this.body
的有效负载是否已转换为json字符串。你应该用
如果您要发送json数据,请在发送请求之前JSON.stringify(this.body)
。
你应该在你的post()
方法中使用map()/ catch()来实际映射响应并捕获实际错误。
所以你的代码应该如下所示
<强> 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?