Nodejs - 对 returns Promise 的函数进行大量 'X' 次调用

Nodejs - Making a very large 'X' amount of calls to a function that returns a Promise one at a time

我有一个用例,我需要以串行方式多次调用异步 NPM 库(>100,000 次)。这是针对程序中的 compliance/research-related 任务,该任务将 运行 一夜之间(运行时不是很重要)。我无法从同一台机器同时调用库。话虽这么说,我不需要将之前的响应瀑布式插入到后来的响应中……请求完全独立于彼此,唯一的限制是库无法处理来自同一台机器的并发请求。

在高层次上,我将 NPM 库调用作为返回 Promise 的函数。我的问题是我不知道如何编写一个程序来处理以自动方式一次发送那么多请求。如果我正在处理已知数量的小 (<5) 请求,我可以简单地将它们与 .then() 语句显式链接在一起,甚至使用回调嵌套而不是 Promises。如果它是一个比我现在处理的 N > 100,000 小得多的未知数,我会编写一个可以在 .then() 中递归调用自身的函数。递归方法是我现在正在做的,它适用于大约 500 的样本量,但永远不会工作到 100,000 或更多深度。我的问题是:如何编写一个程序来自动处理以同步方式发出的这些请求而不使用递归?

这是我目前用于处理小得多的请求样本的递归解决方案的抽象示例。 inputs 是一个包含每个 NPM 调用信息的列表。 inputs 中的每一项都对应于我必须进行的对 NPM 库的调用。

let recursiveRunner = (index) => {
  // basecase
  if (index >= inputs.length) {
    // do stuff at end
    return;
  }

  let input = inputs[index];
  myPromisifiedNpmCall(input)
    .then(result => {
        // store my result appropriately
        someStoreResultFunction(result)
        // recursive call
        recursiveRunner(index + 1);
    })
    .catch(err => {
        // do stuff here
    });
};

// kick off recursiveRunner
recursiveRunner(0)

我建议使用第 3 方库,例如 async series, to have more flow control over your asynchronous tasks. If you need them to run on parallel, then take a look at async parallel

好像不需要递归,简单循环就可以解决。这是 async..await 的完美用例,它允许类似同步的控制流:

async function runner() {
  for (let i = 0; i < inputs.length; i++) {
    try {
      const input = inputs[i];
      const result = await myPromisifiedNpmCall(input);
      someStoreResultFunction(result);
    } catch (err) {...}
  }
}

这大致相当于资源效率较低的 ES6 代码:

function runner() {
  let promise = Promise.resolve();

  for (let i = 0; i < inputs.length; i++) {    
    promise = promise
    .then(() => {
      const input = inputs[i];
      return myPromisifiedNpmCall(input);
    })
    .then(result => {
      someStoreResultFunction(result);
    })
    .catch(err => {...});
  }

  return promise;
}