控制javascript异步流的速率(在循环中)

Seb*_*ien 5 javascript loops asynchronous exec

假设您要在短代码中为列表中的每个文件夹启动(随机)进程:

var exec = require('child_process').exec;
var folders = [...]; // a list from somewhere

_.each(folders, function(folder) {
    exec("tar cvf " + folder + ".tgz " + folder);
});
Run Code Online (Sandbox Code Playgroud)

如果列表很长,我可能最终会同时运行大量进程,这是应该避免的.以受控速率运行执行的相当简单的方法是什么(这里最多5个并发进程)?

编辑:该问题适用于各种异步流(您要在其中控制速率),而不仅仅是针对exec-over-folders问题.

num*_*8er 6

使用async包及其功能:eachLimit

它的作用相同,lodash但是使用异步流处理并使迭代不会一次超出限制:

var async = require('async');
var exec = require('child_process').exec;
var folders = [...]; // a list from somewhere

var maxProcesses = 5; // 5 items at a time
async.eachLimit(
  folders, // collection
  maxProcesses, // limit
  function(folder, next) { // iterator function. args: item, callback
    var cmd = "tar -cf " + folder + ".tgz " + folder;
    console.log('calling:', cmd);
    exec(cmd, function(err, stdOut, stdErr) { // executing cmd
      if(err) console.error(err); // if error putting to console
      next(); // passing the async flow to handle the next iteration
    });
  },
  function() { // after all iterations finished
    console.log('finished processing commands');
  });
Run Code Online (Sandbox Code Playgroud)

或者使用parallelLimit:

var async = require('async');
var _ = require('lodash');
var exec = require('child_process').exec;
var folders = [...]; // a list from somewhere

var callStack = [];
_.each(folders, function(folder) { // generating our stack of commands
  callStack.push(function(done) {
    var cmd = "tar -cf " + folder + ".tgz " + folder;
    exec(cmd, function(err, stdOut, stdErr) {
      if(err) console.error(err);
      done(null, folder);
    });
  });
});

var maxProcesses = 5; // 5 items at a time
async.parallelLimit(callStack, maxProcesses, function() {console.log('finished');});
Run Code Online (Sandbox Code Playgroud)

"让它看起来更短":)

const
  async = require('async'),
  exec = require('child_process').exec;

let folders = [...]; 
async.eachLimit(folders, 5, 
  (folder, next) => 
    exec("tar -cf " + folder + ".tgz " + folder, () => next()),
    () => console.log('finished'));
Run Code Online (Sandbox Code Playgroud)

const
  async = require('async'),
  exec = require('child_process').exec;

let folders = [...]; 
let commands = folders.map(folder => done => exec("tar -cf " + folder + ".tgz " + folder, () => done());
async.parallelLimit(commands, 5, () => console.log('finished'));
Run Code Online (Sandbox Code Playgroud)



如果这个例子中的任何一个对你不好,或者你的系统非常大,那么让我们尝试使用像rsmq这样的消息队列系统