簡體   English   中英

限制在 Node.js 中循環產生的並發子進程數

[英]Limit the number of concurrent child processes spawned in a loop in Node.js

我正在嘗試使用child_process.spawn在每次調用時使用不同參數在 for 循環中調用 CLI 工具。 到目前為止一切順利,但是如果我想引入最大數量的子進程並且只在前一個進程關閉時繼續生成新進程,我就會遇到麻煩。 當達到有限的子進程數量時,我想通過無限 while 循環停止 for 循環。 但是,子進程似乎永遠不會觸發“關閉”事件。

ls為例(對不起,我想不出一個好的、持久的命令,它會在一段時間后自動退出):

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}`);
  });
}

上面的代碼永遠不會退出,當子進程退出時要記錄在控制台中的字符串永遠不會打印在屏幕上。 如果我刪除 while 循環,所有子進程最終都會毫無問題地完成,但同時允許的進程數沒有限制。

為什么我的代碼不起作用,我如何正確限制循環中產生的子進程的數量? 任何幫助,將不勝感激!

您的代碼不起作用,因為lsCommand()是非阻塞的、異步的。 它所做的只是啟動 spawn 操作,然后立即返回。 因此,您的for循環開始運行,然后您的while循環在for循環的第一次迭代中運行並啟動 max lsCommand()調用,然后它退出。 for循環的后續迭代沒有其他事情可做,因為max lsCommand()調用已經在運行。 因此,由於lsCommand()是非阻塞的,您的for循環結束,它所做的只是啟動max lsCommand()操作,然后您的循環就完成了。 您需要做的是,您必須lsCommand() by monitoring ls.on('close')` 來觀察每個lsCommand() by monitoring的完成情況,然后當每個完成后,您就可以開始另一個。 您可以在下面的代碼中看到我是如何做到的。

你可以做這樣的事情,你創建一個內部函數,它有一個循環來啟動進程,直到你的極限,然后你每次 spawn 操作完成時都繼續調用該函數(每次完成時都會觸發一個) :

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();
}

對於一些更通用的實現,請參閱這些:

循環使用可變 URL 的 api get 請求

Promise.all 消耗了我所有的 RAM

Javascript - 如何控制並行訪問網絡的承諾數量

Nodejs:帶有 URL 列表的異步請求

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM