Angular - HttpInterceptor +异步调用

时间:2017-03-22 13:37:06

标签: angularjs interceptor

我试图理解如何在Ansible 1.5.3中编写一个httpInterceptor。

基于http://www.webdeveasy.com/interceptors-in-angularjs-and-useful-examples/

(function() {
'use strict';

angular
    .module('app', ['ui.router', 'ngStorage', 'angular-loading-bar', 'angular-jwt'])                
    .config(myconfig)
    .run(myrun);

function myconfig($stateProvider, $urlRouterProvider, $provide, $httpProvider) {
    ...
    $provide.factory('httpRequestInterceptor', ['$q', 'MyService', function($q, MyService) {
        return {
            'request': function(config) {
                var deferred = $q.defer();
                MyService.execService().then(function(mydata) {
                    // Asynchronous operation succeeded, modify config accordingly
                    console.log("Async OK")
                    deferred.resolve(config);
                }, function() {
                    // Asynchronous operation failed, modify config accordingly
                    console.log("Async KO")
                    deferred.resolve(config);
                });
                return deferred.promise;
            }
        };
    }]);
    $httpProvider.interceptors.push('httpRequestInterceptor');
}

现在我不明白如何编写MyService(它执行GET)。

我试图在myconfig函数中添加但是我在循环依赖中丢失了:

    $provide.factory('MyService', function($injector) {
      var MyService = {
        async: function() {
          // $http returns a promise, which has a then function, which also returns a promise
          console.log("CIAO")
            var $http = $injector.get('$http');
            var promise = $http.get('refresh_token.json').then(function (response) {
            // The then function here is an opportunity to modify the response
            console.log(response);
            // The return value gets picked up by the then in the controller.
            return response.data;
          });
          // Return the promise to the controller
          return promise;
        }
      };
      return MyService;
    })

有人可以帮助我吗?

的Riccardo

1 个答案:

答案 0 :(得分:0)

分享我的工作解决方案。也许NodeJS Guru可以验证。

的Riccardo

(function() {
'use strict';

angular
    .module('app', ['ui.router', 'ngStorage', 'angular-loading-bar', 'angular-jwt'])                
    .config(myconfig)
    .run(myrun);

function myconfig($stateProvider, $urlRouterProvider, $provide, $httpProvider) {
    ...
    // ----------------------------------------------------------------------
    // Interceptor HTTP request
    // ----------------------------------------------------------------------       
    $provide.factory('MyService', function($injector, $localStorage) {
        var MyService = {
            async: function() {
                // $http returns a promise, which has a then function, which also returns a promise
                //console.log("STO PER FARE UNA CHIAMATA ASINCRONA!!!")
                var $http = $injector.get('$http');
                console.log("REFRESHTOKEN DA INVIARE: " + $localStorage.currentUser.refreshToken)
                // La POST va fatta con x-www-form-urlencoded al fine di evitare CORS
                var promise = $http({
                    method: 'POST',
                    headers: { 
                       'Authorization': undefined,
                       'Content-Type': 'application/x-www-form-urlencoded'
                    },
                    url: "https://xxxxxxxxxx/v1/refreshToken",
                    transformRequest: function(obj) {
                         var str = [];
                         for(var p in obj)
                         str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                         return str.join("&");
                     },
                     data: {
                        "refreshToken": $localStorage.currentUser.refreshToken
                    }
                }).then(function(response) {
                    // The then function here is an opportunity to modify the response
                    // console.log(response);
                    // The return value gets picked up by the then in the controller.
                    return response.data;
                });
                // Return the promise to the controller
                return promise;
            }
        };
        return MyService;
    })

    $provide.factory('httpRequestInterceptor', ['$q', "MyService", "$localStorage", "jwtHelper", '$injector', function($q, MyService, $localStorage, jwtHelper, $injector) {
        return {
            'request': function(config) {
                if (config.url.indexOf("/v1/refreshToken") >= 0) {
                    /* Se la request e' generata verso l'endpoint di refreshToken
                       allora salta l'interceptor al fine di evitare dipendenze circolari */
                    console.log("INFO1: SKIP " + config.url);
                    return config;
                } else if (config.url.indexOf(".html") >= 0) {
                    /* Se e' l'include di una view, salta l'inteceptor */
                    console.log("INFO2: SKIP " + config.url);
                    return config;
                } else if (!$localStorage.currentUser || !$localStorage.currentUser.refreshToken) {
                    /* Se non c'e' una sessione aperta oppure la sessione non prevede refresh 
                       allora salta l'interceptor */
                    console.log("INFO3: SKIP nessun token");
                    return config;
                } else if ($localStorage.currentUser.refresh_in_corso == true) {
                    /* Se ci sono diverse chiamate Ajax solo la prima viene fermata.
                       Infatti, visto che l'accessToken non e' del tutto scaduto,
                       e' possibile far coesistire per qualche istante il vecchio 
                       accessToken con quello nuovo ottenuto dal processo di refresh */
                    console.log("INFO4: SKIP refresh in corso");
                    return config;    
                } else {
                    var $http = $injector.get('$http');
                    var guard_period = 5 * 60 // seconds
                    var current_timestamp = Math.floor(Date.now() / 1000);
                    var exp_timestamp_guard = $localStorage.currentUser.exp - guard_period
                    console.log("NEEDREFRESH" + exp_timestamp_guard + "  -->  " + new Date(exp_timestamp_guard * 1000))
                    console.log("NOW        " + current_timestamp + "  -->  " + new Date(current_timestamp * 1000))
                    if (current_timestamp <= exp_timestamp_guard) {
                        console.log("INFO5: SKIP non in zona critica");
                        return config;    
                    } else {
                        console.log("INFO6: refresh necessario")
                        $localStorage.currentUser.refresh_in_corso = true;
                        /* Si è nella zona prossima allo scadere del token di accesso
                           E' possibile richiedere il refresh */
                        console.log("Sono in config: " + config.url + " e apro una chiamata async")
                        var deferred = $q.defer();
                        MyService.async().then(function(mydata) {
                            console.log("Funzione asincrona terminata con successo")
                            // Asynchronous operation succeeded, modify config accordingly                                
                            try {
                                 var plainPayload = jwtHelper.decodeToken(mydata.accessToken);
                                 // store useruid and token in local storage to keep user logged in between page refreshes
                                 $localStorage.currentUser = {
                                     userUid: plainPayload.usr.uid,
                                     systemName: plainPayload.usr.sn,
                                     exp: plainPayload.exp,
                                     accessToken: mydata.accessToken,
                                     refreshToken: mydata.refreshToken,
                                     user: mydata.user,
                                     refresh_in_corso: true
                                 };                  

                                 // add jwt token to auth header for all requests made by the $http service
                                 $http.defaults.headers.common.Authorization = 'Bearer ' + mydata.accessToken;

                                 $localStorage.currentUser.refresh_in_corso = false;

                                 console.log("NUOVO HEADER AUTH: " + $http.defaults.headers.common.Authorization)
                            }
                            catch (err) {
                                $localStorage.currentUser.refresh_in_corso = false;
                                console.log("Token errato. Il refresh non sara' possibile: " + err)
                            }
                            deferred.resolve(config);
                        }, function() {
                            // Asynchronous operation failed, modify config accordingly
                            console.log("Async KO")
                            deferred.resolve(config);
                        });
                        return deferred.promise;
                    }
                }
            }
        };
    }]);
    $httpProvider.interceptors.push('httpRequestInterceptor');
}