最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why refresh token is called twice in axios interceptors - Stack Overflow

programmeradmin5浏览0评论

With the following code, it's work on almost all my pages except one where I load many tabs in same time (eager tab on vuetify2)

expected:

  • send http request
  • if response is 401 (token is expired) we get a new fresh token and rerty all request with new token.
  • if response is 200, continue

But in this page I get:

  • send http request
  • get 10 response 401 (9 response to 10:15:10 and 1 to 10:15:11) (1 seconde)
  • get fresh token and remake 9 request
  • get fresh token again and remake other request

Why the last request dont use the same token ? How can I do to avoid to create a new token again if the old is valid)

let isTokenRefreshing = false;
let subscribers = [];
let refreshTokenPromise = null;  // Nous allons utiliser cette variable pour partager la promesse de rafraîchissement du token entre toutes les requêtes.

function onTokenRefreshed(token) {
    console.log("Token refreshed:", token);
    // Relance toutes les requêtes qui attendaient le token
    subscribers.forEach(callback => callback(token));
    subscribers = []; // Vide la file d'attente
}

function subscribeToTokenRefresh(callback) {
    console.log("Nouvelle requête ajoutée à la file d'attente.");
    subscribers.push(callback); // Ajoute les callbacks dans la file d'attente
}

window.axios.interceptors.response.use(
    response => response, // Si la réponse est OK, on la retourne
    async error => {
        const originalRequest = error.config;

        // Vérifie si c'est bien une erreur 401 et que la requête n'a pas déjà été retentée
        if (error.response && error.response.status === 401 && !originalRequest._retry) {
            console.log("401 détectée, tentative de rafraîchissement du token.");


            // Si le token est déjà en cours de récupération, on attend
            if (refreshTokenPromise) {
                console.log("Le rafraîchissement du token est déjà en cours, on attend...");
                return new Promise((resolve, reject) => {
                    subscribeToTokenRefresh(token => {
                        originalRequest.headers['Authorization'] = `Bearer ${token}`; // Mets à jour l'en-tête pour cette requête
                        resolve(axios(originalRequest)); // Relance la requête d'origine avec le nouveau token
                    });
                });
            }

            console.log("Détails de la requête originale qui a échoué avec 401 :");
            console.log("URL de la requête:", originalRequest.url);
            console.log("Méthode de la requête:", originalRequest.method);
            console.log("Headers de la requête:", originalRequest.headers);



            // Marque cette requête comme étant en cours de réessai
            originalRequest._retry = true;

            console.log("Démarrage du rafraîchissement du token...");
            // Si ce n'est pas encore fait, on initialise la promesse de rafraîchissement du token
            refreshTokenPromise = axios.post('/api/refresh-token') // Remplacez cette URL par votre API de rafraîchissement de token
                .then(response => {
                    const newToken = response.data.token;
                    console.log("Nouveau token récupéré :", newToken);

                    // Sauvegarde du nouveau token (par exemple, dans localStorage, Vuex, etc.)
                    localStorage.setItem('UserToken', newToken);

                    const user = {
                        isLoggedIn: true,
                        user: response.data.user
                    };
                    localStorage.setItem('User', JSON.stringify(user));

                    // On relance toutes les requêtes qui attendaient
                    onTokenRefreshed(newToken);

                    // Retourne le nouveau token
                    return newToken;
                })
                .catch(err => {
                    console.error("Erreur lors du rafraîchissement du token :", err);
                    return Promise.reject(err);
                })
                .finally(() => {
                    // Réinitialise la promesse de rafraîchissement du token
                    refreshTokenPromise = null;
                });

            // Maintenant on attend que la promesse de rafraîchissement se termine
            const newToken = await refreshTokenPromise;

            // Relance la requête initiale avec le nouveau token
            originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
            return axios(originalRequest);
        }

        return Promise.reject(error); // Autres erreurs, on les passe
    }
);
发布评论

评论列表(0)

  1. 暂无评论