Here is a view of my compiled JavaScript, I used TypeScript and also provided this code. In general, I would suggest 2 additional templates:
- Save "refreshTokenInProcess" as a local storage variable in addition to the class variable. This will help maintain a single constant value to indicate whether an update is in progress.
- Track retryCount and maxRetryCount to make sure the loop is not happening. You can also perform another task if the number of repetitions is exceeded. After a successful update, retryCount is reset.
Javascript
var TestServices = /** @class */ (function () { function TestServices($window, $injector, $http, $q) { var _this = this; this.$window = $window; this.$injector = $injector; this.$http = $http; this.$q = $q; this.tokenRefreshing = function () { var deferred = _this.$q.defer(); // Run refresh token service only once in case multiple requests are failing _this.retryCount++; var refreshToken = _this.$window.localStorage.getItem('refresh_token'); var clientId = _this.$window.localStorage.getItem('client_id'); var apiUrl = _this.$window.localStorage.getItem('apiUrl'); var param = 'grant_type=refresh_token&refresh_token=' + refreshToken + '&client_id=' + clientId; _this.$http = _this.$http || _this.$injector.get('$http'); _this.$http.post(apiUrl + 'token', param, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }). then(function (success) { _this.$window.localStorage.setItem('token', success.data.access_token); _this.$window.localStorage.setItem('refresh_token', success.data.refresh_token); _this.$window.localStorage.setItem('client_id', 'web'); _this.$window.localStorage.setItem('expires', success.data['.expires']); _this.refreshTokenInProcess = false; // reset the retry count _this.retryCount = 0; deferred.resolve(success); }, function (err) { _this.refreshTokenInProcess = false; deferred.reject(err); }); return deferred.promise; }; } Object.defineProperty(TestServices.prototype, "refreshTokenInProcess", { get: function () { if (this.$window) { this._refreshTokenInProcess = this.$window.localStorage.getItem('refreshTokenInProcess') === 'true'; } return this._refreshTokenInProcess === true; }, set: function (value) { this._refreshTokenInProcess = value === true; var strValue = value === true ? 'true' : 'false'; if (this.$window) { this.$window.localStorage.setItem('refreshTokenInProcess', strValue); } }, enumerable: true, configurable: true }); TestServices.prototype.executeRequest = function (config) { var accessToken = this.$window.localStorage.getItem('token'); if (accessToken !== 'null') { config.headers.authorization = 'bearer ' + accessToken; } this.lastRequest = config; return config; }; TestServices.prototype.request = function (config) { return this.executeRequest(config); }; TestServices.prototype.responseError = function (response) { var _this = this; if (response.status === 406 && response.data === 'Unauthenticated Token.') { // retry logic if (this.refreshTokenInProcess === false && this.retryCount < this.maxRetryCount) { this.refreshTokenInProcess = true; this.tokenRefreshing().then(function () { return _this.$http(_this.executeRequest(response.config)).then(function (data) { if (data) { response.config.callerController(data.data); } }); }); } } return response; }; return TestServices; }());
Typescript
export class TestServices implements ng.IHttpInterceptor { private _refreshTokenInProcess: boolean; get refreshTokenInProcess(): boolean { if (this.$window) { this._refreshTokenInProcess = this.$window.localStorage.getItem('refreshTokenInProcess') === 'true'; } return this._refreshTokenInProcess === true; } set refreshTokenInProcess(value: boolean) { this._refreshTokenInProcess = value === true; const strValue = value === true ? 'true' : 'false'; if (this.$window) { this.$window.localStorage.setItem('refreshTokenInProcess', strValue); } } lastRequest: any; maxRetryCount: 10; retryCount: 0; constructor(public $window: ng.IWindowService, public $injector: ng.auto.IInjectorService, public $http: ng.IHttpService, public $q: ng.IQService) { } executeRequest(config: ng.IRequestConfig) { const accessToken = this.$window.localStorage.getItem('token'); if (accessToken !== 'null') { config.headers.authorization = 'bearer ' + accessToken; } this.lastRequest = config; return config; } request(config: ng.IRequestConfig) { return this.executeRequest(config); } tokenRefreshing = () => { const deferred = this.$q.defer(); // Run refresh token service only once in case multiple requests are failing this.retryCount++; const refreshToken = this.$window.localStorage.getItem('refresh_token'); const clientId = this.$window.localStorage.getItem('client_id'); const apiUrl = this.$window.localStorage.getItem('apiUrl'); const param = 'grant_type=refresh_token&refresh_token=' + refreshToken + '&client_id=' + clientId; this.$http = this.$http || this.$injector.get('$http'); this.$http.post(apiUrl + 'token', param, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }). then((success: any) => { this.$window.localStorage.setItem('token', success.data.access_token); this.$window.localStorage.setItem('refresh_token', success.data.refresh_token); this.$window.localStorage.setItem('client_id', 'web'); this.$window.localStorage.setItem('expires', success.data['.expires']); this.refreshTokenInProcess = false; // reset the retry count this.retryCount = 0; deferred.resolve(success); }, (err: any) => { this.refreshTokenInProcess = false; deferred.reject(err); }); return deferred.promise; } responseError(response: any) { if (response.status === 406 && response.data === 'Unauthenticated Token.') { // retry logic if (this.refreshTokenInProcess === false && this.retryCount < this.maxRetryCount) { this.refreshTokenInProcess = true; this.tokenRefreshing().then(() => { return this.$http(this.executeRequest(response.config)).then((data: any) => { if (data) { response.config.callerController(data.data); } }); }); } } return response; } }
source share