Angular2/Rxjs : 'catch' on observable giving ProgressEvent instead of json from response

标签 angular typescript rxjs

在我的 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/

相关文章:

angular - 使用元数据在 angular2 中创建动态表单

javascript - 错误类型错误 : Cannot set property 'paginator' of undefined

TypeScript——一些高级类型推断的问题;尝试为 Rematch 构建更好的类型

javascript - 缓冲条形码扫描仪的击键

javascript - 在 API 调用 NgRx Angular 之前检查商店

angular - 从 Controller Ionic 2 更改元素样式

angular - 如何从 visual studio 2015 update 3 的构建中排除 node_module 文件夹

带有 ControlValueAccessor 和 formControlName 的 Angular Material Datepicker

javascript - 访问 mqtt 回调范围之外的类属性

angular - 在 forkJoin 中使用 mergeMap 来获取一个依赖于另一个的可观察对象