我有一个函数可以对服务进行REST调用并返回一个promise。让我们调用该函数Execute()。该函数接受一个ID并将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新手。
答案 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
按顺序执行异步任务,安排调用同一个函数是包含元素的原始数组,否则返回结果数组
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;
答案 2 :(得分:0)
您可以按功能包装promise
并将其推入array
。
将array
分成几块并用reduce
处理。