【问题标题】:Write http interceptor as class将http拦截器编写为类
【发布时间】:2014-01-14 22:10:00
【问题描述】:

我在用普通的 TypeScript 编写有角度的 http 拦截器时遇到了麻烦。我要转换的代码如下:

.config(['$httpProvider', function ($httpProvider) {

    var interceptor = ['$rootScope', '$q', 'httpBuffer', function ($rootScope, $q, httpBuffer) {
        function success(response) {
            return response;
        }

        function error(response) {
            if (response.status === 401 && !response.config.ignoreAuthModule) {
                var deferred = $q.defer();
                httpBuffer.append(response.config, deferred);
                $rootScope.$broadcast('event:auth-loginRequired', response);
                return deferred.promise;
            }
            // otherwise, default behaviour
            return $q.reject(response);
        }

        return function (promise) {
            return promise.then(success, error);
        };

    }];
    $httpProvider.responseInterceptors.push(interceptor);
}])

第一部分很清楚,编写一个带有构造函数的类,该构造函数接受三个依赖项$rootScope$qhttpBuffer。还要写两个私有方法successresponse

class MyInterceptorClass {
    constructor(private $rootScope: ng.IRootScopeService, private $q: ng.IQService, private httpBuffer: HttpBuffer) {
    }

    private success(response: ng.IHttpPromiseCallbackArg<any>): ng.IHttpPromiseCallbackArg<any> {
        return response;
    }

    private error(response: ng.IHttpPromiseCallbackArg<any>): ng.IHttpPromiseCallbackArg<any> {
        if (response.status == 401 && !((<any>response.config).ignoreAuthModule)) {
            var deferred = this.$q.defer();
            this.httpBuffer.append(response.config, deferred);
            this.$rootScope.$broadcast('event:auth-loginRequired', response);

            return deferred.promise;
        }

        // Otherwise, default behavior
        return this.$q.reject(response);
    }
}

拦截器的注册也要明确:

.config(['$httpProvider', ($httpProvider: ng.IHttpProvider)=> {
    $httpProvider.responseInterceptors.push(['$rootScope', '$q', 'httpBuffer', MyInterceptorClass]);
}]);

我遇到的问题是原始 JavaScript 的最后一部分,即匿名函数的返回值。我将如何在 TypeScript 中创建它?据我了解,这将是 TypeScript 中的无名方法,但这是不可能的。

【问题讨论】:

    标签: javascript angularjs typescript


    【解决方案1】:

    配置设置如下

        .config(['$httpProvider', function ($httpProvider: ng.IHttpProvider) {
            $httpProvider.interceptors.push(AuthenticationInterceptor.Factory);
        }])
    

    你的实际课程应该如下所示

    module Common.Security {
    'use strict';
    
    export class AuthenticationInterceptor {
    
        public static Factory($q: ng.IQService) {
            return new AuthenticationInterceptor($q);
        }
    
        constructor(private $q: ng.IQService) {
        }
    
        //Method name should be exactly "response" - http://docs.angularjs.org/api/ng/service/$http
        public response(response) {
            console.log(response);
            return response || this.$q.when(response);
        }
    
        public responseError(rejection) {
            console.log(rejection.status);
            if (rejection.status === 401) {
            }
            // Otherwise, default behavior
            return this.$q.reject(rejection);
        }
    }
    

    【讨论】:

    • 我在这段代码中遇到了问题。 $q 出现错误。它显示未定义。另外,你能解释一下这是如何工作的吗?我的意思是何时调用它以及如何创建实例。我对 Angular 和 Typescripts 很陌生
    • 这将不起作用,请参阅线程stackoverflow.com/questions/23211692/…
    • @Abhijeet 如何使 Factory() 声明缩小安全?
    【解决方案2】:

    这就是我将 httpinterceptor 编写为一个类的方式

    module services {
    
    export class ErrorHttpInterceptor {
        public $log:ng.ILogService;
        public $injector:ng.auto.IInjectorService;
    
        public responseError = (_rejection)=>{
           //handle error here
        };
        public request = (config)=>{
            config.withCredentials = true;
            return config;
        };
        public requestError = (rejection)=>{
            var $q:ng.IQService = this.$injector.get("$q");
            this.$log.log("requestError", rejection);
            return $q.reject(rejection);
        };
        static $inject = ['$injector', '$rootScope', '$q', '$window'];
        constructor($injector:ng.auto.IInjectorService, public $rootScope, public $q, public $window){
            this.$log = $injector.get('$log');
            this.$injector = $injector;
        }
      }
    }
    

    注册

     var app =angular.module('foo',[]);
     app.config(['$httpProvider', (_$httpProvider:ng.IHttpProvider)=>{
        _$httpProvider.interceptors.push('ErrorHttpInterceptor');
    
    }]);
    

    【讨论】:

    • 如何注册这样的拦截器?你给$httpProvider.interceptors.push(...);传递了什么参数?
    • 这将如何工作?我的印象是,当我们在interceptors 中传递一个字符串时,angular 要求使用module.factory(...) 使用该名称注册服务。
    • 嗨,我注意到所提供的解决方案都不包括任何类型。这是最佳实践吗?还是函数应该返回某种类型?我的响应返回了 ng.IHttpPromiseCallbackArg,如果我只是想返回响应,它会起作用,但是当我尝试返回拒绝时,类型会发生冲突。删除类型修复它......但看起来我们真的应该使用某种类型。
    【解决方案3】:

    你需要做: 公众响应 = (response) => {}

    public responseError = (rejection) => { }

    因为以其他方式,您的“this”将是未定义的。 要了解您为什么需要这个:https://www.youtube.com/watch?v=tvocUcbCupA&hd=1

    【讨论】:

      【解决方案4】:

      配置设置如下

          .config(['$httpProvider', function ($httpProvider: ng.IHttpProvider) {
              $httpProvider.interceptors.push(AuthenticationInterceptor.Factory);
          }])
      

      你的实际课程应该如下所示

      module Common {
      'use strict';
      
      export class AuthenticationInterceptor {
      
          private static _instance: AuthenticationInterceptor;
      
          public static Factory($q: ng.IQService) {
              AuthenticationInterceptor._instance = new AuthenticationInterceptor($q);
      
              return AuthenticationInterceptor._instance;
          }
      
          constructor(private $q: ng.IQService) {
          }
      
          //Method name should be exactly "response" - http://docs.angularjs.org/api/ng/service/$http
          public response(response) {
              var self = Common.AuthenticationInterceptor._instance;
      
              console.log(response);
              return response || self.$q.when(response);
          }
      
          public responseError(rejection) {
              var self = Common.AuthenticationInterceptor._instance;
      
              console.log(rejection.status);
              if (rejection.status === 401) {
              }
      
              // Otherwise, default behavior
              return self.$q.reject(rejection);
          }
      }
      

      有必要获取具有完整命名空间的类的实例,因为当接收来自 Angular 的回调时,'this' 是未定义的。

      【讨论】:

      • 感谢您的回答。我也遇到了“这个”总是未定义的问题。为什么会这样?
      【解决方案5】:

      按名称注册:$httpProvider.interceptors.push('myInterceptorClass');

      然后确保您的课程也注册为服务:

      yourApp.service('myInterceptorClass',MyInterceptorClass)

      【讨论】:

      • 这无助于我关于如何实现最后一个匿名方法的问题。
      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2014-02-09
      • 2015-11-30
      相关资源
      最近更新 更多