2017-04-18 3 views
1

J'utilise axios pour envoyer des requêtes à l'API Deezer. Malheureusement, avec l'API de Deezer lorsque vous demandez des albums d'un artiste, cela n'inclut pas les pistes d'album. Donc, je travaille autour de cela en demandant les albums de l'artiste, puis en effectuant une demande axios ultérieure pour chaque album. Le problème que je rencontre est que l'API limite les demandes à 50 par 5 secondes. Si un artiste a plus de 50 albums, je reçois généralement une erreur "quota dépassé". Existe-t-il un moyen de limiter les requêtes axios à 50 par 5 secondes, en particulier lors de l'utilisation de axios.all?Throttling Axios Requests

var axios = require('axios'); 

function getAlbums(artistID) { 
    axios.get(`https://api.deezer.com/artist/${artistID}/albums`) 
    .then((albums) => { 
     const urls = albums.data.data.map((album) => { 
     return axios.get(`https://api.deezer.com/album/${album.id}`) 
      .then(albumInfo => albumInfo.data); 
     }); 
     axios.all(urls) 
     .then((allAlbums) => { 
      console.log(allAlbums); 
     }); 
    }).catch((err) => { 
     console.log(err); 
    }); 
} 

getAlbums(413); 

Répondre

1

Tout d'abord, nous allons voir ce que vous vraiment besoin. Votre but ici est de faire une requête au maximum toutes les 100 millisecondes, si vous avez un grand nombre d'albums. (En utilisant axios.all pour cette question n'est pas différent d'utiliser Promise.all, vous voulez juste attendre que toutes les demandes à remplir.)

Maintenant, avec Axios vous avez l'API d'interception, permettant de brancher votre logique avant les demandes. Vous pouvez donc utiliser un intercepteur comme ceci:

function scheduleRequests(axiosInstance, intervalMs) { 
    let lastInvocationTime = undefined; 

    const scheduler = (config) => { 
     const now = Date.now(); 
     if (lastInvocationTime) { 
      lastInvocationTime += intervalMs; 
      const waitPeriodForThisRequest = lastInvocationTime - now; 
      if (waitPeriodForThisRequest > 0) { 
       return new Promise((resolve) => { 
        setTimeout(
         () => resolve(config), 
         waitPeriodForThisRequest); 
       }); 
      } 
     } 

     lastInvocationTime = now; 
     return config; 
    } 

    axiosInstance.interceptors.request.use(scheduler); 
} 

Ce qu'il fait est le timing demande si elles sont réalisées à intervalles intervalMs millisecondes.

Dans votre code:

function getAlbums(artistID) { 
    const deezerService = axios.create({ baseURL: 'https://api.deezer.com' }); 
    scheduleRequests(deezerService, 100); 

    deezerService.get(`/artist/${artistID}/albums`) 
     .then((albums) => { 
      const urlRequests = albums.data.data.map(
        (album) => deezerService 
         .get(`/album/${album.id}`) 
         .then(albumInfo => albumInfo.data)); 

      //you need to 'return' here, otherwise any error in album 
      // requests will not propagate to the final 'catch': 
      return axios.all(urls).then(console.log); 
     }) 
     .catch(console.log); 
} 

Ceci est, cependant, une approche simpliste, dans votre cas, vous aimeriez probablement recevoir les résultats aussi vite que possible pour le nombre de demandes moins de 50. Pour cela, vous devez ajouter une sorte de compteur à l'intérieur du planificateur qui comptera le nombre de demandes et retardera leur exécution en fonction de l'intervalle et du compteur.