Axios: Ajout d'un paramètre de nouvelle tentative

Créé le 27 nov. 2015  ·  23Commentaires  ·  Source: axios/axios

J'ai une API qui renvoie de temps en temps ECONNRESET . J'aimerais donc réessayer sur une telle erreur. Prévoyez-vous d'ajouter la fonctionnalité retry à cette bibliothèque ?

Commentaire le plus utile

@mericsson J'ai trop besoin d'un ralentissement exponentiel lors de la nouvelle tentative. J'ai rassemblé ce qui suit qui fonctionne très bien. Vous pouvez ajouter la vérification des erreurs/codes d'état spécifiques, car cela ne fait actuellement qu'intercepter et réessayer toutes les erreurs.

axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // If config does not exist or the retry option is not set, reject
    if(!config || !config.retry) return Promise.reject(err);

    // Set the variable for keeping track of the retry count
    config.__retryCount = config.__retryCount || 0;

    // Check if we've maxed out the total number of retries
    if(config.__retryCount >= config.retry) {
        // Reject with the error
        return Promise.reject(err);
    }

    // Increase the retry count
    config.__retryCount += 1;

    // Create new promise to handle exponential backoff
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });

    // Return the promise in which recalls axios to retry the request
    return backoff.then(function() {
        return axios(config);
    });
});

Utiliser:

axios.get('/some/endpoint', { retry: 5, retryDelay: 1000 })
    .then(function(res) {
        console.log('success', res.data);
    })
    .catch(function(err) {
        console.log('failed', err);
    });

Options de configuration :
retry - Nombre de fois où réessayer la demande après la première demande ayant échoué.
retryDelay - Nombre de millisecondes à attendre entre les requêtes échouées (valeur par défaut à 1).

Je peux rendre cela un peu plus configurable dans l'essentiel à un moment donné.

Tous les 23 commentaires

Une mise à jour pour ceci?

Je pense que c'est très important. Le scénario peut-être que lorsque nous implémentons Axios pour le Web mobile, l'utilisateur bascule alors la source Internet du WiFi vers n'importe quel type de connexion mobile.

Je ne pense pas que ce genre de fonctionnalité devrait être dans cette bibliothèque. Si vous en avez besoin, vous pouvez créer un intercepteur pour cela.

@jtangelder des idées à quoi cela devrait-il ressembler ?

function retryFailedRequest (err) {
  if (err.status === 500 && err.config && !err.config.__isRetryRequest) {
    err.config.__isRetryRequest = true;
    return axios(err.config);
  }
  throw err;
}
axios.interceptors.response.use(undefined, retryFailedRequest);

Quelque chose comme ça! Il réessaye 500 erreurs une fois.

Je suis d'accord avec @jtangelder pour

@jtangelder @mzabriskie merci ! en fait, c'est aussi un excellent exemple pour la documentation

+1 J'aimerais que cet exemple soit plus facile à trouver !

@jtangelder merci beaucoup pour l'extrait

Une petite correction sur le snippet, je pense que le statut d'erreur renvoyé devrait être 504 au lieu de 500.

@jtangelder exemple très utile.

Je me demande, avez-vous des idées sur la façon de faire quelque chose avec un ralentissement exponentiel ? Est-il possible de retourner une promesse de retryFailedRequest ? Ou d'autres suggestions ? Merci!

L'exemple dans @jtangelder doit être inclus dans la page du livre de recettes

Vous pouvez maintenant utiliser axios-retry pour cela.

Je suis d'accord. Cela devrait vraiment faire partie de la bibliothèque, ou du moins être mieux documenté.

@mericsson J'ai trop besoin d'un ralentissement exponentiel lors de la nouvelle tentative. J'ai rassemblé ce qui suit qui fonctionne très bien. Vous pouvez ajouter la vérification des erreurs/codes d'état spécifiques, car cela ne fait actuellement qu'intercepter et réessayer toutes les erreurs.

axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // If config does not exist or the retry option is not set, reject
    if(!config || !config.retry) return Promise.reject(err);

    // Set the variable for keeping track of the retry count
    config.__retryCount = config.__retryCount || 0;

    // Check if we've maxed out the total number of retries
    if(config.__retryCount >= config.retry) {
        // Reject with the error
        return Promise.reject(err);
    }

    // Increase the retry count
    config.__retryCount += 1;

    // Create new promise to handle exponential backoff
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });

    // Return the promise in which recalls axios to retry the request
    return backoff.then(function() {
        return axios(config);
    });
});

Utiliser:

axios.get('/some/endpoint', { retry: 5, retryDelay: 1000 })
    .then(function(res) {
        console.log('success', res.data);
    })
    .catch(function(err) {
        console.log('failed', err);
    });

Options de configuration :
retry - Nombre de fois où réessayer la demande après la première demande ayant échoué.
retryDelay - Nombre de millisecondes à attendre entre les requêtes échouées (valeur par défaut à 1).

Je peux rendre cela un peu plus configurable dans l'essentiel à un moment donné.

@KyleRoss Merci pour le code, j'ai fait un ajustement pour que les tentatives soient exponentielles

// Create new promise to handle exponential backoff. formula (2^c - 1 / 2) * 1000(for mS to seconds)
    const backOffDelay = config.retryDelay 
        ? ( (1/2) * (Math.pow(2, config.__retryCount) - 1) ) * 1000
        : 1;

    const backoff = new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        },  backOffDelay);
    });

@KyleRoss Merci pour le partage.

Le délai peut être réglé de plus en plus :

const RETRY_TIMEOUTS = [1, 3, 5, 10]; // seconds
const delay = RETRY_TIMEOUTS[config.retryCount] * 1000;

Si vous souhaitez réessayer une requête 4xx ou 5xx, vous devez travailler avec l'objet d'erreur comme ceci :

Pour intercepter vos demandes :

axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

Pour intercepter vos réponses :

axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });

Des idées géniales. J'ai rassemblé une bonne partie de cela dans un module npm, si les gens sont intéressés :
https://github.com/JustinBeckwith/retry-axios

Heureux de répondre aux demandes de fonctionnalités ✨

axios-retry vs retry-axios

@KyleRoss J'ai essayé d'ajouter les options de configuration retry et retryDelay à AxiosRequestConfig mais il ne semble pas qu'elles existent. Comment as-tu fait pour que ça marche ?

@lawloretienne vous devez vous assurer d'ajouter le code dans mon exemple avant d'utiliser l'un des paramètres de nouvelle tentative. Puisqu'il agit plus comme un plugin, les nouvelles propriétés ne sont pas documentées dans le cadre d'axios lui-même.

config.__retryCount = config.__retryCount || 0;

@KyleRoss Impossible de transmettre la configuration de configuration, chaque 'config.__reyCount' est indéfini.
https://github.com/axios/axios/blob/v0.19.0/lib/core/mergeConfig.js
Les propriétés personnalisées sont désormais filtrées.

La configuration personnalisée de

axios.defaults.headers.common['retry'] = 3
axios.defaults.headers.common['retryDelay'] = 1000
axios.defaults.headers.common['retryCount'] = 0

@mericsson J'ai trop besoin d'un ralentissement exponentiel lors de la nouvelle tentative. J'ai rassemblé ce qui suit qui fonctionne très bien. Vous pouvez ajouter la vérification des erreurs/codes d'état spécifiques, car cela ne fait actuellement qu'intercepter et réessayer toutes les erreurs.

axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // If config does not exist or the retry option is not set, reject
    if(!config || !config.retry) return Promise.reject(err);

    // Set the variable for keeping track of the retry count
    config.__retryCount = config.__retryCount || 0;

    // Check if we've maxed out the total number of retries
    if(config.__retryCount >= config.retry) {
        // Reject with the error
        return Promise.reject(err);
    }

    // Increase the retry count
    config.__retryCount += 1;

    // Create new promise to handle exponential backoff
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });

    // Return the promise in which recalls axios to retry the request
    return backoff.then(function() {
        return axios(config);
    });
});

Utiliser:

axios.get('/some/endpoint', { retry: 5, retryDelay: 1000 })
    .then(function(res) {
        console.log('success', res.data);
    })
    .catch(function(err) {
        console.log('failed', err);
    });

Options de configuration :
retry - Nombre de fois où réessayer la demande après la première demande ayant échoué.
retryDelay - Nombre de millisecondes à attendre entre les requêtes échouées (valeur par défaut à 1).

Je peux rendre cela un peu plus configurable dans l'essentiel à un moment donné.

Merci pour l'aide!

Cette page vous a été utile?
0 / 5 - 0 notes