javascript - 限制在给定时间打开的 promise 数量

标签 javascript typescript promise throttling

以下 TypeScript 一次执行对 doSomething(action) 的每次调用。 (这意味着列表中的第二项在第一项完成之前不会被调用)。

async performActionsOneAtATime() {
    for (let action of listOfActions) {
        const actionResult = await doSomethingOnServer(action);
        console.log(`Action Done: ${actionResult}`);
    }
 }

这将立即向服务器发送所有请求(无需等待任何响应):

async performActionsInParallel() {
    for (let action of listOfActions) {
        const actionResultPromise = doSomething(action);
        actionResultPromise.then((actionResult) => {
            console.log(`Action Done: ${actionResult}`);
        });
    }
}

但我真正需要的是一种抑制它们的方法。一次可能有 10 或 20 个调用打开。 (一次一个太慢了,但是全部 600 个会使服务器过载。)

但我很难弄明白这一点。

关于如何限制一次打开 X 的调用次数有什么建议吗?

(这个问题使用 TypeScript,但我可以使用 ES6 JavaScript 回答。)

最佳答案

您可以在一个简短的函数中完成此操作。 (根据 naomik 的建议按顺序返回值。谢谢!)

/**
 * Performs a list of callable actions (promise factories) so
 * that only a limited number of promises are pending at any
 * given time.
 *
 * @param listOfCallableActions An array of callable functions,
 *     which should return promises.
 * @param limit The maximum number of promises to have pending
 *     at once.
 * @returns A Promise that resolves to the full list of values
 *     when everything is done.
 */
function throttleActions(listOfCallableActions, limit) {
  // We'll need to store which is the next promise in the list.
  let i = 0;
  let resultArray = new Array(listOfCallableActions.length);

  // Now define what happens when any of the actions completes.
  // Javascript is (mostly) single-threaded, so only one
  // completion handler will call at a given time. Because we
  // return doNextAction, the Promise chain continues as long as
  // there's an action left in the list.
  function doNextAction() {
    if (i < listOfCallableActions.length) {
      // Save the current value of i, so we can put the result
      // in the right place
      let actionIndex = i++;
      let nextAction = listOfCallableActions[actionIndex];
      return Promise.resolve(nextAction()).then(result => {
        // Save results to the correct array index.
        resultArray[actionIndex] = result;
      }).then(doNextAction);
    }
  }

  // Now start up the original <limit> number of promises.
  // i advances in calls to doNextAction.
  let listOfPromises = [];
  while (i < limit && i < listOfCallableActions.length) {
    listOfPromises.push(doNextAction());
  }
  return Promise.all(listOfPromises).then(() => resultArray);
}

// Test harness:

function delay(name, ms) {
  return new Promise((resolve, reject) => setTimeout(() => {
    console.log(name);
    resolve(name);
  }, ms));
}

var ps = [];
for (let i = 0; i < 10; i++) {
  ps.push(() => delay("promise " + i, Math.random() * 3000));
}

throttleActions(ps, 3).then(result => console.log(result));

关于javascript - 限制在给定时间打开的 promise 数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38385419/

相关文章:

javascript - 使用日期精度比较 javascript/jquery 中的两个日期

javascript - 文本节点上 "nodeValue"属性的类型 == IE9 中的 "unknown"

typescript - 为什么当 tsc 找不到时 vscode 给我错误 "No Inputs where found in file tsconfig.json"?

class - 在 TypeScript 的类中实现索引器

node.js - 即使我返回 404,我的 promise 的成功 block 也总是执行

javascript - mxGraph:使用 XML 创建图形

javascript - 没有索引javascript的循环

angular - 如何在 Angular 9+ 中隐藏生产中的 console.log

javascript - 以惯用方式组织 javascript webdriver Promise 代码

javascript - 如何将 API 作为 $.Deferred() 的一部分进行轮询