Javascript 限制Node.js中循环中生成的并发子进程的数量

Javascript 限制Node.js中循环中生成的并发子进程的数量,javascript,node.js,concurrency,child-process,Javascript,Node.js,Concurrency,Child Process,我正在尝试使用child\u process.spawn调用for循环中的CLI工具,每次调用该工具时都使用不同的参数。到目前为止还不错,但若我想引入最大数量的子进程,并且只在前一个进程关闭时继续生成新进程,那个么我就会遇到麻烦。我想在达到有限的子进程数量时,使用无限while循环停止for循环。但是,子进程似乎从不触发“关闭”事件 以ls为例(很抱歉,我想不出一个好的、持久的命令可以在一段时间后自动退出): const{spawn}=require(“child_进程”); 常数max=3;

我正在尝试使用
child\u process.spawn
调用for循环中的CLI工具,每次调用该工具时都使用不同的参数。到目前为止还不错,但若我想引入最大数量的子进程,并且只在前一个进程关闭时继续生成新进程,那个么我就会遇到麻烦。我想在达到有限的子进程数量时,使用无限while循环停止for循环。但是,子进程似乎从不触发“关闭”事件

ls
为例(很抱歉,我想不出一个好的、持久的命令可以在一段时间后自动退出):

const{spawn}=require(“child_进程”);
常数max=3;
设电流=0;
//dirsToVisit是一个路径数组
for(设i=0;i=max){}
电流++;
lsCommand(dirsToVisit[i]);
}
函数lsCommand(dir){
常量ls=spawn(“ls”,[dir]);
ls.on(“关闭”,代码=>{
当前--;
log(`Finished with code${code}`);
});
}
上面的代码永远不会退出,子进程退出时要记录在控制台中的字符串永远不会打印在屏幕上。如果删除while循环,所有子进程最终都会顺利完成,但不会限制同时允许多少个进程


为什么我的代码不起作用,如何正确限制循环中生成的子进程的数量?任何帮助都将不胜感激

您的代码无法工作,因为
lsCommand()
是非阻塞、异步的。它所做的只是启动繁殖操作,然后立即返回。因此,您的
for
循环开始运行,然后您的
while
循环在
for
循环的第一次迭代中运行,并启动max
lsCommand()
调用,然后退出。由于
max
lsCommand()
调用已经在运行,因此
for
循环的后续迭代没有其他事情可做。因此,由于
lsCommand()
是非阻塞的,因此
for
循环完成,它所做的只是启动
max
lsCommand()
操作,然后循环完成。您需要做的是通过监视ls.on('close')`来监视每个
lsCommand()的完成情况,然后在每个命令完成后,您可以启动另一个命令。您可以在下面的代码中看到我是如何做到这一点的

您可以这样做,即创建一个内部函数,该函数有一个循环来启动进程,直到达到您的极限,然后在每次生成操作完成时继续调用该函数(每次完成时将再触发一个):

函数列表dirs(dirsToVisit,maxAtOnce){
设numRunning=0;
设指数=0;
函数runMore(){
//虽然我们需要开始更多,但要开始更多
while(numRunning{
--numRunning;
log(`Finished with code${code}`);
runMore();
}).on(“错误”,err=>{
--numRunning;
runMore();
});
}
如果(numRunning==0){
//这里的所有请求都已完成
}
}
runMore();
}
有关一些更通用的实现,请参见以下内容:


谢谢您的建议,我们马上就可以试用了!你知道为什么我的代码不起作用吗?:)@John-我在回答的开头添加了一段,解释了代码无法正常工作的原因。
const { spawn } = require("child_process");

const max = 3;
let current = 0;

// dirsToVisit is an array of paths
for (let i = 0; i < dirsToVisit.length; i++) {
  // if already running 3 ls, wait till one closes
  while (current >= max) {}
  current++;
  lsCommand(dirsToVisit[i]);
}

function lsCommand(dir) {
  const ls = spawn("ls", [dir]);
  ls.on("close", code => {
    current--;
    console.log(`Finished with code ${code}`);
  });
}
function listDirs(dirsToVisit, maxAtOnce) {
    let numRunning = 0;
    let index = 0;

    function runMore() {
        // while we need to start more, start more of them
        while (numRunning < maxAtOnce && index < dirsToVisit.length) {
            ++numRunning;
            const ls = spawn("ls", [dirsToVisit[index++]]);
            ls.on("close", code => {
                --numRunning;
                console.log(`Finished with code ${code}`);
                runMore();
            }).on("error", err => {
                --numRunning;
                runMore();
            });
        }
        if (numRunning === 0) {
            // all done with all requests here
        }
    }
    runMore();
}