Wait for Axios Request Interceptor to complete before sending another ajax call

One feature I have added is a request interceptor for all axios calls. This interceptor checks the JWT token and automatically refreshes it if necessary.

axios.interceptors.request.use((config) =>{

    const currentState = store.getState(); // get updated state
    const currentTime = Math.floor( new Date().getTime() / 1000 );

    if( 
        !currentState.app.jwtRefreshOnRequest 
        && currentTime >= currentState.jwt.expires - 120
        && currentState.jwt.refresh_before > currentTime
    ){ // token expiring in 2 minutes, trigger refresh    

        //dispatch({type: 'JWT_REFRESH_REQUEST'});
        axios.get( API_BASE_URL + '/auth/refresh')
            .then(function(response){
                // dispatch({type: 'JWT_REFRESH_SUCCESS', payload: response.data});
                axios(config).then(resolve, reject);
            })
            .catch(function(err){               
                reject(err);
        });

    }       

    return config;
}); 

Although this code successfully triggers token refresh and saves the new one, there's an issue where the original call does not wait for the interceptor request to finish, resulting in the use of the expired token.

Therefore, it seems like I need to make synchronous calls from the interceptor.

Answer №1

It's crucial to avoid synchronous calls when making HTTP requests in order to prevent your application from hanging.

The key here is to ensure that all of your calling code is asynchronous - whether you're using callbacks, promises, or anything async-related, everything should be handled asynchronously.

When working with axios.get, it's important to remember that it returns a Promise, which keeps track of the asynchronous HTTP request and resolves once it's complete. Instead of returning the config, you need to return this promise.

To achieve this, you can create a new Promise - if a new token HTTP request is necessary, it will wait for it; otherwise, it can resolve immediately.

axios.interceptors.request.use(config =>
    new Promise((resolve, reject) => {
        // ... your code ...

        axios.get( API_BASE_URL + '/auth/refresh')
            .then(response => {
                const newConfig = getConfigFromResponse(response);
                resolve(newConfig);
            }, reject);

        resolve(config);
    })
}); 

When you encounter the then method, you're dealing with a Promise, indicating that everything should return a Promise when working asynchronously.

Using async/await makes this process much simpler. These modern browser-supported keywords allow you to place the Promise call inline with the await keyword, streamlining the code significantly.

axios.interceptors.request.use(async config =>

    // ... your code ...

    if(/* We need to get the async token */) {
        const response = await axios.get( API_BASE_URL + '/auth/refresh');
        config = getConfigFromResponse(response);
    }

    return config;
}); 

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

Sliding elements horizontally with jQuery from right to left

I recently purchased a WordPress theme and I'm looking to customize the JavaScript behavior when the page loads. Currently, my titles animate from top to bottom but I want to change this behavior dynamically. You can view it in action here: I have ...

Transferring information from socket.io to vue.js

I am currently facing an issue with passing socket.io data to a Vue.js element. Despite going through the Vue documentation multiple times, I have not been able to find a solution. The data is being sent to the client via socket.io and successfully logged ...

Retrieving information from an object using a randomly generated identifier

Imagine having an object structured like this. var foo = { "dfsghasdgsad":{ "name":"bob", "age":"27" } }; The variable foo will consistently only have one object, but the key is dynamically created. How can I access the values "bob" and "27" ...

What is the best method to detect a change in scroll position on a webpage using JavaScript?

Is there a way to trigger an event when the page's scroll position changes? I'm interested in creating a dynamic table of contents similar to (where the active item changes as you scroll). Can this be achieved without directly accessing the cu ...

Using jQuery with AJAX for retrieving data and returning a value

I've come across this script: function getUsername() { $.ajax("http://one2xs.com/index.php", { success: function(a) { console.log($(a).find("#left").html().match(/Je bent ingelogd als ([ ^A-z0-9]*)/)[1]); return $( ...

Sharing JavaScript code between Maven modules can be achieved by following these steps

My Maven project has a unique structure that includes: "Base" module -- containing shared Java files -- should also include shared JavaScript files Module 1 -- using shared Java files as a Maven dependency -- should utilize shared JavaScript files throug ...

Use vue.js to add a block of content after every sixth iteration in a loop

Currently, I have a list of offer cards rendering through a loop. I am adding a row div every 3rd column (bootstrap) element. Now, I need to also add another column element (banner block) for every 6th element in order to achieve a layout like the one show ...

Tips for unit testing an Angular Service that is primarily responsible for redirecting to an external page from the application

My service is responsible for redirecting to a separate login page since we are implementing login as a service. function redirectToMembership() { var returnURL = $location.host(); returnURL+="/#/Authorization"; $window.location.href=Environme ...

jQuery for validating input fields with positive integers only using regular expressions

I currently have two input fields in my HTML that look like this: <input type="text" class="txtminFeedback" pattern="^\d+([\.\,][0]{2})?$" placeholder="Minimum Feedback"> <input type="text" class="txtmaxFeedback" pattern="^\d ...

Tips for adding an asterisk to the label of a Material-UI switch component

I am trying to include an asterisk symbol in the label by passing a required prop with a property, but it doesn't seem to be functioning correctly. <FormControlLabel control={ <Switch onChange={event => ...

Using Flask to pass variable data from one route to another in Python using the `url

I am facing an issue with sending a variable value to Python from Flask HTML/JS via url_for(). Here's my Python code: @app.route('/video_feed/<device>') def video_feed(device): # return the response generated along with the speci ...

When directed to a different page, Fetch does not activate

Having trouble getting the fetch function to run more than once in my application. It works the first time, loading the page with received data, but when I navigate to a new URL without refreshing the page, nothing changes - not even the state. The same is ...

How can I display SQL results in a Jade page using Node, Express, and MySQL?

My application built with Node.js and Express is connected to a MySQL database for monitoring purposes. The code structure is as follows: In the Node file: app.get('/banners', function(req,res){ connection.query("SELECT * FROM banner_store_ ...

Issue with parsing JSON data in jQuery Ajax requests

Trying to utilize php and jquery ajax with json datatype method for sending data. Check out the code below: $("#username").on("keyup change keypress", function () { var username = $("#username").val(); $.ajax ({ type: "POST", // method ...

Exploring the world of SPA: Implementing Data Transfer Objects

Considering implementing a Single Page Application (SPA) using a JavaScript framework like Angular JS. Currently, I have multiple existing Web APIs containing the necessary information for the app. I need to add another API that will handle new data and re ...

Spring Boot Ajax Parse Error - issue with returning object to Ajax success function

When I make a jQuery ajax call to my Spring controller, I am trying to send back an object to fill out a form in an iziModal. The data gets sent from the browser to the controller and runs through the method, but then I hit a roadblock. I'm having tro ...

Alternative way to search for child elements within an element without the use of jQuery

I am in the process of creating a universal set of functions to verify the existence of children with specific attributes within a particular element. Unfortunately, I do not have access to jQuery for this task. Here is an example function call: has_chil ...

Unfortunately, CSS3 PIE is not compatible with border-radius and box-shadow properties

I created a basic HTML/CSS code for testing purposes, but I'm having trouble getting the library to function properly. I've placed the .htc, .php and .js files in the same directory as index.html, but it just won't work. Check out the code ...

Issue with displaying a vTable component in VueJS / Vuetify

I am struggling with this basic HTML/Vue/Vuetify code snippet below, and I can't seem to get it functioning as intended. const { createApp, computed, ref, reactive } = Vue; const { createVuetify } = Vuetify; const ...

Encountering an issue with Next.js React SSR using styled-jsx: unable to access the 'state' property as

I've come across a problem that I can't seem to figure out. Despite my attempts to search for a solution here, I haven't been able to help myself. I'm new to javascript and react, so please bear with me. Issue: I'm using React (1 ...