2017-07-28 18 views
6

Tôi hiện đang sử dụng đoạn mã sau để rethrow một yêu cầu mà trả về một 401 từ API của tôi:Làm thế nào để xử lý nhiều phản ứng trong góc responseError chặn

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); 
      } 

này hoạt động tuyệt vời cho 1 yêu cầu, nhưng nó doesn' t dường như làm việc nếu tôi nhận được hai 401 trở lại từ một trang duy nhất, chẳng hạn như khi trang đang tải với hai cuộc gọi api để cư trú các phần khác nhau. Làm thế nào tôi có thể nhận được đánh chặn của tôi để rethrow nhiều cuộc gọi hoãn lại?

Ngoài ra, không nên đánh lửa cho mỗi 401 riêng lẻ? Không lý tưởng, nó sẽ gây ra nhiều cuộc gọi làm mới trên một trang duy nhất, nhưng cải thiện từ dữ liệu bị thiếu do cuộc gọi không bị thu hồi.

Ảnh chụp màn hình:

enter image description here

+2

* không nên lửa đánh chặn cho mỗi 401 cá nhân * - nó cần. Nếu điều này không xảy ra, vui lòng cung cấp http://stackoverflow.com/help/mcve. Một plunk/fiddle có khả năng tái tạo vấn đề có thể hữu ích. – estus

+0

Bạn nhận được hai 401 vì bạn đang tắt, song song, hai XHR với mã thông báo cũ. Vấn đề gì gây ra? Liệu nó cuối cùng có được dữ liệu hợp lệ cho cả hai XHR? – georgeawg

+0

@georgeawg Hành vi tôi thấy là hai yêu cầu không đồng bộ được sử dụng để điền trang, cả 401, yêu cầu thứ 2 được trả về và nói rằng tôi có một lựa chọn cho mỗi cuộc gọi, lựa chọn thứ nhất trống, thứ 2 có dữ liệu. – RandomUs1r

Trả lời

1

Một cách tiếp cận là để tiết kiệm lời hứa token và chuỗi các lần thử lại lần thứ hai và tiếp theo cho đến khi làm mới thẻ hoàn tất:

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; 
    } 
} 

Trong ví dụ trên từ chối xử lý tạo ra một lời hứa làm mới mã thông báo và sau đó vô hiệu hóa nó khi các thanh toán làm mới mã thông báo (hoặc hoàn thành hoặc bị từ chối). Nếu một từ chối khác xảy ra trong khi làm mới mã thông báo đang được tiến hành, hãy thử lại trong chuỗi (và bị trì hoãn) cho đến khi XHR làm mới mã thông báo hoàn tất.

+0

Điều đó nghe có vẻ chính xác như những gì tôi cần, tuy nhiên tôi đã đăng một ảnh chụp màn hình được cập nhật với mã tại chỗ, có vẻ như nó trả về một yêu cầu duy nhất giống như yêu cầu cũ của tôi. Bạn không chắc chắn cách khắc phục, nhưng tokenPromise ở trên biết về nhiều yêu cầu như thế nào? – RandomUs1r

1

khá giống georgeawg câu trả lời ...

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

Tôi đã chụp ảnh này sáng nay, việc chụp mạng cũng giống như vậy. Tôi đang đi với điều này là không thể làm với hai yêu cầu async với một interceptor trong Angular 1.6. Tuy nhiên, tôi có thể làm cho các cuộc gọi của tôi không đồng bộ bằng cách chuỗi các lời hứa của họ trên một cấp độ trang và sau đó nó hoạt động, vì vậy tôi đoán tôi đang đi với kế hoạch B. – RandomUs1r

Các vấn đề liên quan