在我的 HttpServive
中,我共享了处理开始/结束加载栏、为 JWT 设置正确 header 等的 http 方法。
一切都很好,但现在我想在 catch
中添加一些逻辑来检查非 200 状态代码(例如 401)的响应,这样我就可以做一些事情然后重新发出失败的请求。
问题是,无论出于何种原因,我都无法从该 catch
访问非 200 状态代码时返回的响应。
例如,这是代码:
// ...
return this.http[method](url, options || defaultOptions)
.map((res: Response) => res.json()) // <--- gives JSON from response
.catch((error: any)) => {
console.log(error);
console.log(error.json()); // <--- should give JSON from response, but gives ProgressEvent instead
return Observable.throw(error.json()); // also gives ProgressEvent when I 'subscribe' to the observable
})
.finally(() => {
this.loadingBarService.complete();
});
console.log(error)
输出Response
类型的错误; console.log(error.json())
输出一些 ProgressEvent
类型的数据。
为什么我收到的是 ProgressEvent,而不是从非 200 状态代码响应发送的 JSON?
这是 ProgressEvent
:
{
bubbles: false,
cancelBubbles: false,
cancelable: false,
composed: false,
currentTarget: XMLHttpRequest,
defaultPrevented: false,
eventPhase: 0,
isTrusted: true,
lengthComputable: false,
loaded: 0,
path: Array(0),
returnValue: true,
srcElement: XMLHttpRequest,
target: XMLHttpRequest,
timeStamp: 1234.115,
total: 0,
type: "error",
__proto__: ProgressEvent
}
如您所见,ProgressEvent
不是我的响应。我的响应是一个只有一个 error
属性的 JSON 对象,其中包含一条消息和一个状态。这是错误的,为什么我没有收到回复?
最佳答案
我在基于 Angular 和 Asp.Net Core 的水疗项目中遇到了类似的问题。
如果是同一个问题,它应该取决于客户端从服务器接收到的 http 响应中缺少 CORS header 。 此响应违反了浏览器 CORS 策略,并且很可能取决于服务器中未处理的运行时错误。
即使捕获所有错误并将一些信息和 http 状态放入返回响应中,Angular 在发生 CORS 约束违规时,也不允许访问任何响应信息,甚至是 http 状态,因此它会产生“空”响应:
Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers, …} headers : Headers {_headers: Map(0), _normalizedNames: Map(0)} ok : false status : 0 statusText : "" type : 3 url : null..
我通过这种方式将 CORS header 放入 ASp.Net Core api 服务器返回给客户端的响应中解决了这个问题:
app.UseExceptionHandler(appError => {
appError.Run(async context => {
var _config = ServiceProviderFactory.ServiceProvider.GetService<AppConfigurations>();
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
context.Response.Headers.Add("Access-Control-Allow-Origin", $"{_config.AngularSiteUrl}");
context.Response.Headers.Add("Access-Control-Allow-Headers", "access-control-allow-origin,authorization,content-type");
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if (contextFeature != null) {
var ex = contextFeature.Error;
var sp = services.BuildServiceProvider();
var _logger = sp.GetService<IGenericRepository<Log>>();
_logger.AddAndSave(new Log {
Description = "Exception not handled occurred",
Reason = ex.ToString(),
Type = "Error"
});
await context.Response.WriteAsync(
JsonConvert.SerializeObject(new {
Status = context.Response.StatusCode,
Message = "Internal Server Error."
}));
}
});
代码必须放在Startup
类的Configure
方法中。
希望对您有所帮助。
关于Angular2/Rxjs : 'catch' on observable giving ProgressEvent instead of json from response,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43705854/