在node.js中分叉循环的正确方法是什么

时间:2018-03-13 13:09:55

标签: node.js for-loop fork

所以我创建了一个收集数据并在永无止境的循环中将其写入db的服务器。

server.listen(3001, () => {
doFullScan();
});

async function doFullScan() {
    while (true) {
        await collectAllData();
    }
}

collectAllData()是一种检查可用项目的方法,循环遍历每个项目收集一些数据并将其写入db。

async function collectAllData() {
    //doing soemhting
    const projectNames = ['array with projects name'];

    //this loop takes too much of time
    for(let project in projectNames){
        await collectProjectData(project);
   }
   //doing something
}

问题是整个循环花费了太多时间。所以我想通过多线程循环加速它并使用我的所有计算机核心。

我该怎么办?

https://nodejs.org/docs/latest/api/cluster.html上有一些包含示例的集群库,但我不想创建新的服务器。我想产生儿童,这将完成任务并在完成工作后退出。

所以有const { fork } = require('child_process');但我不确定如何让每个fork只运行collectProjectData()方法。

2 个答案:

答案 0 :(得分:1)

您可以在没有任何第三方库的情况下本地执行此操作。 现在,您的for...loop正在逐个运行。

选项1

使用Promise.all.map

await Promise.all(projectNames.map(async(projectName) => {
  await collectProjectData(projectName);
});

请注意,如果您使用.map,它将同时启动所有这些,如果projectNames继续增长,则可能会过多。 这与你目前所做的完全相反。

选项2

有一个中间方式......按顺序运行批次,但是每个批次内的项目是异步的。

const chunk = (a, l) => a.length === 0 ? [] : [a.slice(0, l)].concat(chunk(a.slice(l), l));
const batchSize = 10;
const projectNames = ['array with projects name'];

let projectNamesInChunks = chunk(projectNames, batchSize);
for(let chunk of projectNamesInChunks){
  await Promise.all(chunk.map(async(projectName) => {
    await collectProjectData(projectName);
  });
}

答案 1 :(得分:0)

我建议使用Promise.map http://bluebirdjs.com/docs/api/promise.map.html

这样你就可以像这样控制并发级别:

await Promise.map(projectNames, collectProjectData, {concurrency: 3})