Angular - Resending unsuccessful requests

We have successfully incorporated token authorization with refresh token logic into our application. While everything is functioning as expected, we are looking to enhance the retry mechanism for requests that fail due to token expiration. The entire process is managed within the Interceptor module of our codebase. Below is a snippet of the relevant code:

a.service('APIInterceptor', function ($q, $rootScope, $location, $window,    $injector) {
var service = this;
var $http;
var refreshTokenInProcess = false;

executeRequest = function (config) {
    var accessToken = $window.localStorage.getItem('token');
    if (accessToken != 'null') {
        config.headers.authorization = "bearer " + accessToken;
    }
    lastRequest = config;
    return config;
};
service.request = function (config) {
    return executeRequest(config);
};
var tokenRefreshing = function () {
    var deferred = $q.defer();
    // Implementing a one-time token refresh in case of multiple failed requests
    if (refreshTokenInProcess == false) {
        var refreshToken = $window.localStorage.getItem('refresh_token');
        var clientId = $window.localStorage.getItem('client_id');
        var apiUrl = $window.localStorage.getItem('apiUrl');

        var param = "grant_type=refresh_token&refresh_token=" + refreshToken + "&client_id=" + clientId;
        $http = $http || $injector.get('$http');
        $http.post(apiUrl + 'token', param, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).
        then(function (success) {
            $window.localStorage.setItem('token', success.data.access_token);
            $window.localStorage.setItem('refresh_token', success.data.refresh_token);
            $window.localStorage.setItem('client_id', "web");
            $window.localStorage.setItem('expires', success.data[".expires"]);
            deferred.resolve(success);
            refreshTokenInProcess = false;
        }, function (err) {
            deferred.reject(err);
        });
    }
    else
        deferred.resolve();
    refreshTokenInProcess = true;
    return deferred.promise;
};
service.responseError = function (response) {
    if (response.status === 406 && response.data === "Unauthenticated Token.") {
            // Retry logic
            tokenRefreshing().then(function () {
                return $http(executeRequest(response.config)).then(function (data) {
                    if (data)
                        response.config.callerController(data.data);
                })
            });
    }
};

While the system functions properly with individual failed requests, we have observed an issue where retries start looping when multiple failed requests occur over longer periods. We have attempted to resolve this by using the refreshTokenInProcess flag, but unsuccessful so far. Any suggestions or design patterns you can recommend would be greatly appreciated.

Thank you

Answer №1

Here's a snippet of my compiled JavaScript code where I utilized TypeScript for better structure and clarity. I have also included two additional patterns that I recommend:

  1. Consider storing the 'refreshTokenInProcess' as both a local storage variable and a class variable to maintain a single persisted value indicating the refresh status.
  2. Implement tracking for retryCount and maxRetryCount to prevent looping. You can take alternative actions if the retry count exceeds its limit. The retry count resets after a successful refresh.

JavaScript

// Your JavaScript code goes here

TypeScript

// Your TypeScript code goes here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Chart: Observing the Discrepancy in the Initial X-Axis Points

I'm working on incorporating multiple charts onto one page, with each chart centered and stacked one after the other. I've set a fixed width for the graph canvas. The challenge arises from the varying ranges of tick values - one chart may have a ...

Failed to load JSON data from the factory

Recently, I started learning AngularJS and have been struggling to fetch JSON data from a factory. The error message I keep getting is not very helpful: TypeError: Cannot read property '1' of null This is the module I am working with: var app ...

Include jQuery, jQuery UI, and plugins seamlessly to avoid any version conflicts

My goal is to inject my custom code into a webpage using a bookmarklet. This code requires jQuery, jQuery UI, and additional plugins to be included on the page. I'm aware of the noConflict function, but I have concerns about potential conflicts if ot ...

angular: the world of guarantees and assistance

I'm struggling to grasp the concept of promises. I understand what they are supposed to do, but when it comes to writing or debugging them, I hit a roadblock. MyController.js (function() { angular.module('WizmoApp').controller('St ...

Perform $watch or $observe a single time

I have a watch and an observe that perform the same function. Sometimes, both of them run simultaneously, causing the function to execute twice during a digest cycle. Is there a way to prioritize either the watch or the observe, ensuring only one of them ...

Transform a Python dictionary into a JavaScript object and be able to retrieve both the key and the value

Having trouble accessing the value or key of a JSON object, as it is displaying as undefined. Attempted to use json.parse but encountered the same issue. now = datetime.now() date_time = now.strftime("%m/%d/%Y, %H:%M:%S") print(date_time) chatrooms[chatr ...

Tips for efficiently updating state within a loop using the settimeout function in a React application

As I work on my react app to visualize sorting algorithms, I've encountered an issue that has me stumped. I am currently iterating through all elements of the array stored in the 'bars' state and attempting to swap them for testing purposes. ...

Can someone guide me on how to locate and access the port number?

In my Reactjs project root directory, I've created a .env file. This is what's inside my .env file: PORT = 30001 ... In my App.tsx file, I'm trying to access the port like this: const PORT_NUMBER = process.env.PORT; When I run yarn start ...

Execute a function that handles errors

I have a specific element that I would like to display in the event of an error while executing a graphql query (using Apollo's onError): export const ErrorContainer: React.FunctionComponent = () => { console.log('running container') ...

What is the method to ensure that the Node REPL solely displays the result?

Is there a way to execute a script in Electron that only logs the output value without displaying all the code? I am utilizing xterm.js and node-pty for this project. For instance, consider the following sample code: // Add your code here function multi ...

Passing parent props to child components in Vue.js - A comprehensive guide!

Trying to understand the process of passing a prop from parent to child components. If I include the prop attribute with the #id within the child component tag, like Image cid="488484-49544894-584854", it functions correctly. However, I am interested in u ...

"Efficiently handle JSON and binary data passing with the enhanced functionality of Express Body Parser

Within my express app router, I have routes set up to handle both POST requests with JSON data and binary data. The issue arises when I use body parser to parse the JSON data, as it incorrectly interprets the binary data as JSON and causes errors during th ...

What is the most efficient way to minimize the use of if statements in an Angular component when calling a specific function?

Currently, I am working on an Angular 7 temperature conversion application. Within my formGroup, there are inputs and outputs along with two multi-select dropdowns where users can choose the unit of temperature 'From' and 'To' for conve ...

Utilize SectionList and a custom header view on Y to achieve a translation effect that creates a visually appealing empty space as

Hello everyone, I am fairly new to React Native and the Animated API. My goal is to create a simple parallax header and an Animated SectionList similar to this demonstration. https://i.stack.imgur.com/R2GBP.gif Below is a snippet of my code: export defa ...

Switching Icon in Vuetify Navigation Drawer Mini Variant upon Click Event

UPDATE Here's the solution I discovered: <v-icon> {{ mini ? 'mdi-chevron-right' : 'mdi-chevron-left' }} </v-icon> Is it feasible to modify the icon when toggling between navigation drawer variants? The default varia ...

Tips for resolving rendering page issues in an express app

My application is a straightforward blog platform that showcases a schema for the title, entry, and date of each blog post. There is also an edit/delete feature that is currently under development. When attempting to use the edit/delete button on a selecte ...

Preventing simultaneous AJAX requests with a single click

I am facing a challenge with handling multiple AJAX requests. Whenever a user clicks on a button, an AJAX request is triggered to enter a record into the database. However, if the user clicks on the button rapidly multiple times, it results in multiple sim ...

What is the method for displaying all items in Angular Material's auto-complete component, even after a selection has been

By default, Angular Material only shows one item from the auto-completion list when selected, hiding the rest. For example, upon clicking the control, it appears like this: https://i.sstatic.net/U8awO.jpg After selecting an item, the remaining list is no ...

Exploring AngularJS: A Guide to Accessing Objects within Directives

I have successfully passed an object from the controller to the directive. However, when trying to access the object within the directive, it seems to be read as a string. Below is the code snippet, and I am trying to extract the City and State from the ...

Incorporate a lightbox within a repeater field in advanced custom fields

I have developed a gallery with dynamic pills using advanced custom fields and I need to add a lightbox to it. I've tried several times to add the code for the lightbox but all my attempts have been unsuccessful. I have already added all the necessar ...