在50个小块中使用Javascript执行100K Promises

时间:2018-01-19 16:34:24

标签: javascript rest promise

我有一个函数可以对服务进行REST调用并返回一个promise。让我们调用该函数Exec​​ute()。该函数接受一个I​​D并将ID作为GET参数发送到REST端点,该端点将ID保存在mongoDB数据库中,并带有一些额外的信息。

在客户端,我需要运行"执行" ID(0到100k)的100k次,并显示每个的状态(是成功还是失败)。

我做了显而易见的事情,我创建了一个从0到100k的循环并运行执行传递" i。这导致我的Chrome最终冻结内存不足(资源不足)。它还会导致后端所有其他呼叫的网络拥塞。

所以我想"砍"那些100k到可管理的数量,如50个承诺呼叫每个。当这50个都完成时(无论是失败还是成功)我想使用 Promise.all([])。然后执行下一个50直到所有100k完成。这样我就可以同时控制网络拥塞和内存。但是,我似乎无法知道如何撼动这一点。这是我的代码。

let promises = []
for (let i = 0; i < 100000, i++)
    {
       promises.push(execute(i))
       if (i % 50 === 0) 
       {
          Promise.all(promises)
          .then  (a => updateStatus (a, true))
          .catch (a => updateStatus (a, false)) 

       }

    }

Javascript的异步特性将继续执行循环的其余部分并执行。我真的不想让计时器每50次迭代保持循环,因为这会阻止UI并使我的应用程序同步。关于我如何解决这个问题的任何建议?

非常感谢。

Javascript新手。

3 个答案:

答案 0 :(得分:1)

使用promises本身,只能通过递归来完成。

如果您可以使用新版本的Node.js,请使用async await,它会按预期工作,然后您可以使用await Promise.all(promises)

如果你不能,那么有一个很好的库可以使用这种方法一次执行50个异步调用:https://caolan.github.io/async/docs.html#parallelLimit

它甚至比块更好,因为如果你在块中有1个慢回调,它将阻止其他所有内容。使用并行限制,它只是一直执行50个回调。 (但是如果你坚持并且使用.series方法,你可以预先创建50块)

答案 1 :(得分:0)

你可以使用async/await按顺序执行异步任务,安排调用同一个函数是包含元素的原始数组,否则返回结果数组

&#13;
&#13;
let arr = Array.from({
  length: 2000
}, (_, i) => i);

let requests = arr.slice(0);

let results = [];

let fn = async(chunks, results) => {
  let curr;
  try {
    curr = await Promise.all(chunks.map(prop => 
             new Promise(resolve => setTimeout(resolve, 500, prop))));
    results.push(curr);
    console.log(curr);
  } catch(err) {
    throw err
  }

  return curr !== undefined && requests.length 
         ? fn(requests.splice(0, 50), results) 
         : results
}

fn(requests.splice(0, 50), results)
.then(data => console.log(data))
.catch(err => console.error(err))
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以按功能包装promise并将其推入array
array分成几块并用reduce处理。

Npm软件包。
https://www.npmjs.com/package/concurrency-promise