Promise.all消耗我所有的RAM

我有一个我使用的API的速率限制器,每秒允许20个请求。 所有的请求都是基于承诺的,一旦有回应,这个承诺将被API数据解决。

问题:

我设置了一个包含58k个承诺的promiseArray,全部等待响应。 所以慢慢地,内存在增加,直到内存不足。 在我的具体情况下,我不需要将parsing的数据传递给我的then() ,数据正在吃掉我所有的RAM。

代码:

  }).then(() => { // 2. Crawl for all clanprofiles from these leaderboards const promiseArray = [] for (let i = 0; i < clanTags.length; i++) { // Resolved data from getClanProfile() is eating up all my RAM const p = backgroundScheduler.getClanProfile(clanTags[i], true) promiseArray.push(p) } return Promise.all(promiseArray) }).then(() => { 

那么有没有办法等到promiseArray解决而不需要parsing的数据呢?

如果您没有58k的承诺,它们相关的asynchronous操作和结果数据立即生效,您将使用较less的内存。

相反,您希望一次运行X操作,然后当您完成一个操作时,您将同时启动下一个不超过X的X操作,同时不会超过X个承诺。

您可以尝试使用适当的X值。值为1的是顺序操作,但是通常可以通过使用更高的X值来提高总体端到端操作时间。如果所有请求都碰到相同的主机,则X是大概不超过5-10(因为给定的主机不能一次做很多事情,要求它做得比一次做得更多,只是放慢了速度)。

如果每个请求都是给不同的主机,那么你可能会使X更高。 实验会给你一个峰值内存使用量和整体吞吐量的最佳值,并且取决于你的具体情况。

Bluebird的Promise.map()有一个并发选项,可以为你做这个,但是也有很多方法可以同时在X中进行编码。

以下是一些pipe理有多less人正在飞行的编码示例:

向一个只能处理20个请求的API发出几个请求

如何执行系列承诺?

由于内存不足而无法完成承诺

一次发送100万个请求100个

如何做到这一点,以便我可以一次执行JavaScript中的10个承诺,以防止API调用的速率限制?


如果你不需要解决的数据,你可以通过将它replace成这样来允许它更快地被更新:

  const p = backgroundScheduler.getClanProfile(clanTags[i], true).then(data => { return 0; // make resolved value just be a simple number // so other data is now eligible for GC }); promiseArray.push(p) 

而且,下面是一个简单的实现,它在同一时间在一个不超过X个请求的情况下迭代一个数组:

 // takes an array of items and a function that returns a promise // runs no more than maxConcurrent requests at once function mapConcurrent(items, maxConcurrent, fn) { let index = 0; let inFlightCntr = 0; let doneCntr = 0; let results = new Array(items.length); let stop = false; return new Promise(function(resolve, reject) { function runNext() { let i = index; ++inFlightCntr; fn(items[index], index++).then(function(val) { ++doneCntr; --inFlightCntr; results[i] = val; run(); }, function(err) { // set flag so we don't launch any more requests stop = true; reject(err); }); } function run() { // launch as many as we're allowed to while (!stop && inflightCntr < maxConcurrent && index < items.length) { runNext(); } // if all are done, then resolve parent promise with results if (doneCntr === items.length) { resolve(results); } } run(); }); }