处理对 API 的 25,000 个 GET 请求

A. *_*ner 0 javascript http node.js axios

所以基本上我试图向 API 发出大量(大约 25,000 个)GET 请求。我使用 axios 作为我的库来进行 HTTP 调用。

所以我有:

dsHistPromises.push(axios.get(url))
Run Code Online (Sandbox Code Playgroud)

然后我正在使用:

axios.all(dsHistPromises)
    .then(function(results) {
      results.forEach(function(response){
        if (format === lists.formats.highlow) {
          storage.darkskyHistoryHighLow.push(requests.parseDarkskyHighLow(response, city))
        }
        // parse data here and print it to files...
      })
    }).catch(err => {
      throw err
    })
Run Code Online (Sandbox Code Playgroud)

履行我所有的承诺。

当我尝试运行我的代码时,我收到如下错误

(node:10400) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: read ECONNRESET
Run Code Online (Sandbox Code Playgroud)

我必须想象这是我正在连接的 API 的问题。服务器可能很难管理我的请求,对吗?

有什么技巧可以解决这个问题吗?

sam*_*ime 5

正如您所怀疑的,我想说这是因为您正在访问的 API。大多数理智的 API 都会有某种限制,以防止某个用户破坏它们。你可能会遇到这种情况。

您需要做的是通过在通话之间设置时间延迟来限制消息传递。

有几种方法可以处理这个问题。一种方法是按顺序进行每个呼叫,一次一个。这将有助于避免服务器的限制,但可能会更慢。

如果服务器允许,您可以并行执行多个请求。

基本上,它看起来像这样:

const urls = getUrlsToCallFromSomewhere();
const delay = 500; // ms

const next = () => {
  if (!urls.length) {
    return; 
  }

  const url = urls.pop();
  axios.get(url).then(data => {
    results.push(data);
    const now = Date.now();

    if (now - start > delay) {
      next();
    } else {
      setTimeout(next, delay - (now - start));
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

这不是超级完美,但应该可以给你一个想法。基本上,一次给他们一个电话。完成后,检查一下已经过去了多长时间。如果您已经达到delay金额,请立即致电。如果没有,请使用setTimeout()等待时间。

您可以安排您的代码以同时进行其中一些操作以加快速度,并根据需要将延迟调整为尽可能长或尽可能快。