diegoaguilar
diegoaguilar

Reputation: 8376

Why can't I return stdout variable in this exec function?

I got a function to call an exec in node.js server. I'm really lost about getting the stdout back. This is function:

function callPythonFile(args) {

    out = null
    var exec = require('child_process').exec,
    child;

    child = exec("../Prácticas/python/Taylor.py 'sin(w)' -10 10 0 10",

    function (error, stdout, stderr) {

    console.log('stderr: ' + stderr)
    if (error !== null) 
        console.log('exec error: ' + error);
    out = stdout
    })
    return out
}

When I call to console.log(stdout) I actually get an output. But when I try to print outside the function, it's output, it'll always be null. I can't really see how I can get it

Upvotes: 0

Views: 3369

Answers (2)

José F. Romaniello
José F. Romaniello

Reputation: 14156

Because you return from the function before the exec is finished and the callback is executed.

Exec in this case is asynchronous and unfortunately there is no synchronous exec in node.js in the last version (0.10.x).

There are two ways to do what you are trying to do.

Wait until the exec is done

var exec = require('child_process').exec,

function callPythonFile (args, callback) {
  var out = null
  exec("../Prácticas/python/Taylor.py 'sin(w)' -10 10 0 10", 
    function (error, stdout, stderr) {
      if (error !== null) 
        callback(err);
      callback(null, out);
    });
}

//then you call the function like this:

callPythonFile(args , function (err, out) {
  console.log('output is', out);
});

You will see this pattern a lot in node.js, instead of returning something you have to pass a callback.

Return a ChildProcess object

The exec function returns a ChildProcess object which is basically an EventEmitter and has two important properties stdout and stderr:

var exec = require('child_process').exec,

function callPythonFile (args) {
  return exec("../Prácticas/python/Taylor.py 'sin(w)' -10 10 0 10");
}

//then you call the function like this:

var proc = callPythonFile(args)
proc.stdout.on('data', function (data) {
  //do something with data
});

proc.on('error', function (err) {
  //handle the error
});

The interesting thing is that stdout and stderr are streams, so you can basically pipe to files, http responses, etc. and there are plenty of modules to handle streams. This is an http server that always call the process and reply with the stdout of the process:

var http = require('http');

http.createServer(function (req, res) {

  callPythonFile(args).stdout.pipe(res);

}).listen(8080);

Upvotes: 3

CFrei
CFrei

Reputation: 3627

Have a look here about the exec: nodejs doc.

The callback function does not really return anything. So if you want to "return" the output, why don't you just read the stream and return the resulting string (nodejs doc)?

Upvotes: 1

Related Questions