2017-07-28 10 views
6

obecnie używam następujący kod do rethrow wniosek zwracającą 401 z mojego API:Jak obsługiwać wiele odpowiedzi kątowej responseError kolektora

responseError: function(rejection) { 
       var authData = localStorageService.get('authorizationData'); 
       if (rejection.status === 401 && authData) { 
        var authService = $injector.get('authService'); 
        var $http = $injector.get('$http'); 
        ̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶ 

        var promise = authService.refreshToken(); 

        return ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶ promise.then(function() { 
         return $http(rejection.config); 
        }); 
       } 
       return $q.reject(rejection); 
      } 

Działa to doskonale na 1 wniosek, ale nie robi” Wydaje się, że działa, jeśli otrzymam dwa 401 z powrotem z jednej strony, na przykład gdy strona ładuje się dwoma wywołaniami api, aby wypełnić różne sekcje. Jak mogę zmusić przechwytującego do ponownego wyrzucenia wielu odroczonych połączeń?

Również, czy nie należy przechwytywać myśliwcem przechwytującym dla każdego 401 osobno? Nie idealne, spowodowałoby to wielokrotne odświeżanie wywołań na pojedynczej stronie, ale ulepszenie wynikające z braku danych z powodu nieodebrania połączenia.

Zrzut ekranu:

enter image description here

+2

* nie powinno ogień przechwytujących indywidualnie dla każdego 401 * - powinno. Jeśli tak się nie stanie, proszę podać http://stackoverflow.com/help/mcve. Pomocne może być plunk/fiddle, które jest w stanie odtworzyć problem. – estus

+0

Otrzymujesz dwa 401, ponieważ odpalasz równolegle dwa XHR ze zużytymi tokenami. Jaki problem powoduje ten problem? Czy w końcu dostanie poprawne dane dla obu XHR? – georgeawg

+0

@georgeawg Zachowanie, które widzę, to dwie asynchroniczne żądania użyte do zapełnienia ognia strony, oba 401, drugie (?) Żądanie zostanie ponownie wysłane i powiedz, że wybieram na jedno połączenie, pierwszy wybór jest pusty, drugi ma dane. – RandomUs1r

Odpowiedz

1

Jednym ze sposobów jest zapisanie tokena obietnicy i łańcuch drugiego i kolejnych ponownych prób aż token odświeżania jest kompletna:

responseError: function(rejection) { 
    var authService = $injector.get('authService'); 
    var $http = $injector.get('$http'); 
    var tokenPromise = null; 

    var authData = localStorageService.get('authorizationData'); 
    if (rejection.status === 401 && authData) { 

     if (!tokenPromise) { 
      tokenPromise = authService.refreshToken() 
       .finally(function() { 
       tokenPromise = null; 
      }); 
     }; 

     return tokenPromise.then(function() { 
      return $http(rejection.config); 
     }); 
    } else { 
     throw rejection; 
    } 
} 

W powyższym przykładzie odrzucenia handler utwórz obietnicę odświeżenia tokena, a następnie usuń ją, gdy odświeżanie tokena zostanie ukorzenione (spełnione lub odrzucone). Jeśli podczas odświeżania tokena wystąpi inne odrzucenie, ponowienie próby w łańcuchu (i opóźnieniu) do czasu zakończenia odświeżania XTR tokenu.

+0

To brzmi dokładnie tak, jak potrzebuję, jednak opublikowałem zaktualizowany zrzut ekranu z kodem w miejscu, wygląda na to, że wyrzucił jedną prośbę, taką jak zrobiła moja stara. Nie wiesz, jak to naprawić, ale w jaki sposób powyższy tokenPromise wie o wielu żądaniach? – RandomUs1r

1

dość podobna georgeawg odpowiedź ...

responseError: function(rejection) { 
       var authData = localStorageService.get('authorizationData'); 
       if (rejection.status === 401 && authData && !isAuthRequest() /* If request for refresh token fails itself do not go into loop, i.e. check by url */) { 
        var authService = $injector.get('authService'); 
        var $http = $injector.get('$http'); 

        var promise = authService.refreshTokenExt(); // look below 

        return ̶promise.then(function() { 
         return $http(rejection.config); 
        }); 
       } 
       return $q.reject(rejection); 
      } 

AuthService:

... 
var refreshAuthPromise; 

service.refreshTokenExt = function() { 
    if (refreshAuthPromise == null) { 
    refreshAuthPromise = authService.refreshToken().catch(function() { 
     // Cant refresh - redirect to login, show error or whatever 
    }).finally(function() { 
     refreshAuthPromise = null; 
    }); 
    } 
    return refreshAuthPromise; 
} 
+0

Tego ranka zrobiłem to, niestety, przechwytywanie sieci wygląda tak samo. Idę z tym nie można zrobić z dwoma żądaniami asynchronicznymi z przechwytywaczem w Angular 1.6. Jednak nie mogę sprawić, by moje połączenia nie były asynchroniczne, łącząc ich obietnice na poziomie poszczególnych stron, a potem to działa, więc myślę, że wybieram z planem B. – RandomUs1r

Powiązane problemy