在 angularjs 拦截器中停止请求

Posted

技术标签:

【中文标题】在 angularjs 拦截器中停止请求【英文标题】:Stop request in angularjs interceptor 【发布时间】:2014-10-17 20:53:52 【问题描述】:

如何在 Angularjs 拦截器中停止请求。

有没有办法做到这一点?

我尝试使用承诺并发送拒绝而不是解决!

.factory('connectionInterceptor', ['$q', '$timeout',
   function($q, $timeout) 
    var connectionInterceptor = 
        request: function(config) 
            var q = $q.defer();
            $timeout(function() 
                q.reject();
            , 2000)
            return q.promise;
            // return config;
        
    
    return connectionInterceptor;
  
])
.config(function($httpProvider) 
   $httpProvider.interceptors.push('connectionInterceptor');
);

【问题讨论】:

发布您尝试过的代码。否则,我们无法向您解释为什么它不起作用,以及如何解决它。 @JBNizet 添加了!请检查代码! 不确定为什么要等待 2 秒,但您的代码运行良好。没有发送 HTTP 请求。见plnkr.co/edit/x4YGC7l4B66RGTmWB7Ts?p=preview。打开您的开发工具,并检查您的网络选项卡:未发送对 README 的请求。现在注释掉拦截器的注册,做同样的测试,你会看到请求出去了,并显示成功警报。 好吧,请注意所有 ajax 请求都会通过您的拦截器,包括加载 html 模板的请求。如果这不是问题,请发布一个重现问题的 plunkr。 检查config.url的值。 【参考方案1】:

我最终使用以下角度拦截器绕过了角度 XHR 调用:

function HttpSessionExpiredInterceptor(sessionService) 
    return 
        request: function(config) 
            if (sessionService.hasExpired()) 
                /* Avoid any other XHR call. Trick angular into thinking it's a GET request.
                 * This way the caching mechanism can kick in and bypass the XHR call.
                 * We return an empty response because, at this point, we do not care about the
                 * behaviour of the app. */
                if (_.startsWith(config.url, '/your-app-base-path/')) 
                    config.method = 'GET';
                    config.cache = 
                        get: function() 
                            return null;
                        
                    ;
                
            

            return config;
        
    ;

这样,任何请求,POST,PUT,...都被转换为 GET,这样缓存机制就可以 由角使用。此时,您可以使用自己的缓存机制,在我的情况下,当 session 过期了,我不再关心返回什么了。

【讨论】:

我知道这是一个旧答案,但这非常聪明。【参考方案2】:

$http 服务有一个选项 超时来完成这项工作。 你可以这样做:

angular.module('myApp')
    .factory('httpInterceptor', ['$q', '$location',function ($q, $location) 
        var canceller = $q.defer();
        return 
            'request': function(config) 
                // promise that should abort the request when resolved.
                config.timeout = canceller.promise;
                return config;
            ,
            'response': function(response) 
                return response;
            ,
            'responseError': function(rejection) 
                if (rejection.status === 401) 
                    canceller.resolve('Unauthorized'); 
                    $location.url('/user/signin');
                
                if (rejection.status === 403) 
                    canceller.resolve('Forbidden');  
                    $location.url('/');
                
                return $q.reject(rejection);
            

        ;
    
    ])
    //Http Intercpetor to check auth failures for xhr requests
   .config(['$httpProvider',function($httpProvider) 
        $httpProvider.interceptors.push('httpInterceptor');
    ]);

【讨论】:

【参考方案3】:

不确定一般情况下是否可行。但是您可以使用“取消器”启动 $http 请求。

这是来自this answer的示例:

var canceler = $q.defer();
$http.get('/someUrl', timeout: canceler.promise).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.

因此,如果您可以控制启动请求的方式,这可能是一个选择。

【讨论】:

我想要一个使用拦截器的通用解决方案! @vipulsodha Whisher 的回答似乎是这个想法的一个很好的实现。【参考方案4】:

我只是以空对象的形式返回

'request': function request(config) 
    if(shouldCancelThisRequest)  
        return ;
    
    return config;

【讨论】:

【参考方案5】:

这对我有用,特别是为了停止传出请求和模拟数据:


app
  .factory("connectionInterceptor", [
    "$q",
    function ($q) 
      return 
        request: function (config) 
          // you can intercept a url here with (config.url == 'https://etc...') or regex or use other conditions
          if ("conditions met") 
            config.method = "GET";
            // this is simulating a cache object, or alternatively, you can use a real cache object and pre-register key-value pairs,
            // you can then remove the if block above and rely on the cache (but your cache key has to be the exact url string with parameters)
            config.cache = 
              get: function (key) 
                // because of how angularjs $http works, especially older versions, you need a wrapping array to get the data
                // back properly to your methods (if your result data happens to be an array). Otherwise, if the result data is an object
                // you can pass back that object here without any return codes, status, or headers.
                return [200, mockDataResults, , "OK"];
              ,
            ;
          
          return config;
        ,
      ;
    ,
  ])
  .config(function ($httpProvider) 
    $httpProvider.interceptors.push("connectionInterceptor");
  );

如果您试图模拟类似的结果

[42, 122, 466]

您需要返回一个带有一些 http 参数的数组,不幸的是,这正是 ng sendReq() 函数的编写方式。 (参见https://github.com/angular/angular.js/blob/e41f018959934bfbf982ba996cd654b1fce88d43/src/ng/http.js#L1414 的第 1414 行或下面的 sn-p)

        // from AngularJS http.js

        // serving from cache
        if (isArray(cachedResp)) 
          resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3], cachedResp[4]);
         else 
          resolvePromise(cachedResp, 200, , 'OK', 'complete');
        

【讨论】:

以上是关于在 angularjs 拦截器中停止请求的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 拦截器没有将 JWT Bearer 放入 node.js 应用程序的每个请求中

如何使用angularJS拦截器只拦截特定的http请求?

Angularjs注入拦截器实现Loading效果

AngularJs HTTP响应拦截器实现登陆权限校验

angularjs拦截器:为啥在$http拦截器中没有收到正确的状态码和消息

使用 AngularJS 拦截器阻止 HTTP 基本身份验证对话框