typescript Angular2:HTTP 错误处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36628498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:24:55  来源:igfitidea点击:

Angular2 : HTTP error handling

typescriptangularrxjs

提问by Pierre Henry

I am trying to reproduce the following behaviour that I successfully implemented using Angular 1.x interceptors and promises, in a Angular2 based Ionic2 app :

我正在尝试在基于 Angular2 的 Ionic2 应用程序中重现我使用 Angular 1.x 拦截器和 promise 成功实现的以下行为:

  1. Intercept HTTP request errors
  2. If the status code is 401, then

    a. make another request to register the client. This will provide some token that I can subsequently attach to each request.

    b. Retry the orignal request and provide the result to the caller through the promise / observable

  3. If the error status is anything other than 401 just let the flow normally to the caller

  1. 拦截 HTTP 请求错误
  2. 如果状态码是 401,那么

    一个。再次请求注册客户端。这将提供一些令牌,我随后可以将其附加到每个请求。

    湾 重试原始请求并通过promise/observable将结果提供给调用者

  3. 如果错误状态是 401 以外的任何其他内容,只需让流程正常流向调用者

NB: The register process does not need any intervention from the user (no login) so I want it to be completely transparent for the user. I register once when the app is first loaded, but the session will eventually expire and I need to automatically re-register.

注意:注册过程不需要用户的任何干预(无需登录),所以我希望它对用户完全透明。我在应用程序首次加载时注册了一次,但会话最终会过期,我需要自动重新注册。

This is the original Angular 1 implementation (I include only the responseErrorpart of the interceptor):

这是原始的 Angular 1 实现(我只包括responseError拦截器的一部分):

responseError : function(rejection){
    if(rejection.status == 401){
        $log.info('Intercepting unauthorized 401 response. Will try to re-register the session and retry the request.');

        var security = $injector.get('SecurityService');
        var $http = $injector.get('$http');

        return security.registerSession().then(function(){
            return $http(rejection.config);
        });

    }else{
        return rejection;
    }
}

Now, I have wrapped Angular2's HTTP service and I can do simple things like adding a header to each request. However I am struggling to reproduce the same behaviour using Angular2 and Observables.

现在,我已经封装了 Angular2 的 HTTP 服务,我可以做一些简单的事情,比如为每个请求添加一个标头。但是,我正在努力使用 Angular2 和 Observables 重现相同的行为。

My attempt so far, this is the request method of my HTTP wrapper that my services will call :

到目前为止,我的尝试是我的服务将调用的 HTTP 包装器的请求方法:

request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

    let req: Request = this.buildRequest(url, options);

    this.beforeCall(req);

    var observable = this.http
        .request(req)
        .retry(3)
        .catch(res => {
            debugger;
            console.log("ERROR! " + res.status);
            if(res.status == 401){
                this.logger.log('Unauthorized request. Trying to register the session and then retry the request.');
                return this.securityService.registerSession().subscribe(() => {
                    // What to do here so the client gets the result of the original request ??
                });
            }
        })
        .do((res:Response) => { this.afterCall(req, res) });

    return observable;
}

采纳答案by Thierry Templier

You could execute again the request after initialize the session using the flatMap operator of observables:

您可以在使用 observables 的 flatMap 运算符初始化会话后再次执行请求:

    var observable = this.http
        .request(req)
        .retry(3)
        .catch(res => {
            debugger;
            console.log("ERROR! " + res.status);
            if(res.status == 401){
                this.logger.log('Unauthorized request. Trying to register the session and then retry the request.');
                return this.securityService.registerSession().flatMap(() => {
                  return this.http.request(req); // <--------
                });
            }
        })
        .do((res:Response) => { this.afterCall(req, res) });

    return observable;
}