Background process, loading bar

Most server-side-scripting languages have an exec function (node, php, ruby, etc). This allows the programming language to interact with the shell.

I wish to use exec() in node.js to run large processes, things I used to do with AJAX requests in the browser. I would like a simple progress / loading bar to display to the user the progress.

I found out the hard way in the example below that the callback / asynchronous nature of the exec function will make this example take over 5 seconds to load.

What I want is some way to get the content of browser to be updated (ajax) with the current state of the execution like a loading bar. But I don't want the ran file to be dependent on the browser.

Any idea?

my route

exports.exec = function(req,res){
  // http://nodejs.org/api.html#_child_processes
  var sys = require('sys')
  var exec = require('child_process').exec;
  var child;
  child = exec("node exec/test.js", function (error, stdout, stderr) {
    var o = {
      "error":error,
      "stdout":stdout,
      "stderr":stderr,
    };
    o = JSON.stringify(o);
    res.send(o);
  });
};

my test.js file

var sys = require('sys');

var count = 0;

var interval = setInterval(
    function(){
        sys.print('hello'+count);
        count++

        if(count == 5){
            clearInterval(interval);
        }

    },
1000);

You should use socket.io for this. Here is a demo app to get you started with socket.io

You emit an event for every 1% using socket.io, the browser listen to it and update a bar.

You can't use exec you need a streamed output.
Therefore you'd rather use child_process.

On the server.

var spawn = require('child_process').spawn,
    exec  = spawn('node exec/test.js');

exec.stdout.on('data', function (message) {
  socket.emit('process', message);
});

On the sub process:

console.log('10%')
// ...
console.log('20%')
// ...
console.log('30%')

If your sub process is a node script you could do something a lot more elegant. Rather than having to talk with a stream stdout you could use the cluster module of node to send messages between the master and the slaves process.

I made a fork of the previous demo app adding a route /exec which demonstrate how to achieve this.

When I'll have more time I'll make another demo app, this is a quite interesting and educational test. Thanks for the idea :D.