Using underscore.js to wrap node.js child_process.spawn

As I was writing jake files to build my projects, I was faced with the problem of spawning new child processes using node’s child_process.spawn. In order to get the output of these child processes on the console, you have to attach on the child process’s stdout ‘data’ event. So my code looked like this.

var child_process = require('child_process');

var child = child_process.spawn(cmd, params.split(' '), {
 cwd: '.'
});

child.stdout.on('data', function(data) {
  process.stdout.write('' + data);
});

child.stderr.on('data', function(data) {
  process.stderr.write('' + data);
});

That does the job. But you have to write this for every process you want to spawn. Everytime the same .stdout.on(‘data’, function(data) { … } stuff. So I thought this would be a great chance to play with the wrap function of underscore.js, so that stdout and stderr would be written to the console per default. The resulting code looks like this.

var child_process = require('child_process');
var underscore = require('underscore');

child_process.spawn = underscore.wrap(child_process.spawn, function(func) {
  // We have to strip arguments[0] out, because that is the function
  // actually being wrapped. Unfortunately, 'arguments' is no real array,
  // so shift() won't work. That's why we have to use Array.prototype.splice 
  // or loop over the arguments. Of course splice is cleaner. Thx to Ryan
  // McGrath for this optimization.
  var args = Array.prototype.splice.call(arguments, 0, 1);

  // Call the wrapped function with our now cleaned args array
  var childProcess = func.apply(this, args);

  childProcess.stdout.on('data', function(data) {
    process.stdout.write('' + data);
  });

  childProcess.stderr.on('data', function(data) {
    process.stderr.write('' + data);
  });

  return childProcess;
});

…

var child = child_process.spawn(cmd, params.split(' '), {
    cwd: '.'
 });

Now everytime you use child_process.spawn, stdout and stderr are tied to process.stdout and process.stderr automatically.

Using underscore.js to wrap node.js child_process.spawn