限制Axios请求

时间:2017-04-18 21:38:53

标签: node.js axios deezer

我使用axios向Deezer API发出请求。不幸的是,当您申请艺术家的专辑时,使用Deezer的API,它不包括专辑曲目。所以,我正在通过请求艺术家的专辑,然后为每张专辑执行后续的axios请求来解决这个问题。我遇到的问题是API将请求限制为每5秒50次。如果一位艺术家拥有超过50张专辑,我通常会超过"配额超过#34;错误。有没有办法将axios请求限制为每5秒50个,特别是在使用axios.all?

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);

2 个答案:

答案 0 :(得分:5)

首先,让我们看看你真正需要什么。如果你有大量的专辑,你的目标是每100毫秒发出一次请求。 (对于此问题使用axios.all与使用Promise.all没有区别,您只想等待所有请求完成。)

现在,使用axios,您可以使用拦截API,允许在请求之前插入逻辑。所以你可以使用这样的拦截器:

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);
}

它的作用是定时请求,因此它们以intervalMs毫秒的间隔执行。

在您的代码中:

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);
}

然而,这是一种简单的方法,在您的情况下,您可能希望尽快收到少于50的请求数。为此,您必须在调度程序中添加某种计数器它将根据间隔和计数器计算请求数并延迟执行。

答案 1 :(得分:0)

这是我使用简单的异步setTimeout / Es6代码的解决方案:

您可以设置睡眠参数功能的延迟时间

const sleep = (delay) => {
  return new Promise(function(resolve) {
    setTimeout(resolve, delay);
  });
}


axios.interceptors.response.use(async function (response) {
    await sleep(3000)
    return response;
  }, function (error) {
    // Do something with response error
    console.error(error)
    return Promise.reject(error);
  });