0

可以向我的 nodejs 服务器发出的一些请求需要大量处理(例如:5000 个文件)。由于请求需要一段时间来处理,我想在浏览器中显示进度。为此,我正在使用 io-socket。服务器定期将进度提前发送给客户端,例如ioSocket.emit("log", "progress 24%).
但是,如果向客户端发送进度通常可以工作,那么当有大量文件时,它就不行了。没有任何东西发送到浏览器。
我确定该过程进展顺利,因为我将进度记录到节点终端,并且它按预期显示。

我想知道如何让 ioSocket.emit 事件在重负载情况下工作,因为这是查看进度最有用的地方。

文件处理函数如下所示:

var child_process = require("child_process");

function (ioSocket) {

  ioSocket.emit("log", "start")

  var ratingCounts = 0;
  var listOfFilesRatings = []

  _.each(listOfFilesPaths, function(path, i){

    child_process.exec("exiftool -b -Rating "+ path, function(err, stdout){

      if (err) console.log(err)
      else {

        listOfFilesRatings.push(stdout);
        ratingCounts++;

        ioSocket.emit("log", "rating test progress "+ ratingCounts)

      };

    });

    ioSocket.emit("log", "each progress "+ i)

  });


}

在这个例子中,只有第一个“开始”发射将被触发到浏览器。

但是,如果我执行以下操作:

function (ioSocket) {

  ioSocket.emit("log", "start")

  for (i=0; i<1000; i++) {

    ioSocket.emit("log", "each progress "+ i)

  };

}

一切正常,我将“开始”和所有“每个进度”发送到浏览器。

4

1 回答 1

2

如果您正在处理 5000 个文件,您的方案将_.each()同时child_process.exec()启动 5000 个 exiftool 进程。这可能会带来任何计算机,除了一些大铁跪在它的膝盖上。当您在特定硬件上运行一些性能测试以确定 N 应该是多少(可能低于 10)时,您可能应该启动不超过 N 个。

这是一种方法:

var child_process = require("child_process");

function processFiles(ioSocket) {

    return new Promise((resolve, reject) => {

        ioSocket.emit("log", "start")

        let ratingCounts = 0;
        let listOfFilesRatings = [];
        const maxInFlight = 10;
        let inFlightCntr = 0;
        let fileIndex = 0;

        function run() {
            // while room to run more, run them
            while (inFlightCntr < maxInFlight && fileIndex < listOfFilesPaths.length) {
                let index = fileIndex++;
                ++inFlightCntr;
                ioSocket.emit("log", "each progress " + index)
                child_process.exec("exiftool -b -Rating " + path, function(err, stdout) {
                    ++ratingCounts;
                    --inFlightCntr;
                    if (err) {
                        console.log(err);
                        listOfFilesRatings[index] = 0;
                    } else {
                        listOfFilesRatings[index] = stdout;
                        ioSocket.emit("log", "rating test progress " + ratingCounts)
                    }
                    run();
                });
            }
            if (inFlightCntr === 0 && fileIndex >= listOfFilesPaths.length) {
                // all done here
                console.log(listOfFilesRatings);
                resolve(listOfFilesRatings);
            }
        }
        run();
    });
}


processFiles().then(results => {
    console.log(results);
});
于 2018-03-16T16:14:13.760 回答