Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

callback in async call called to often #12

Open
WegDamit opened this issue Sep 8, 2017 · 1 comment
Open

callback in async call called to often #12

WegDamit opened this issue Sep 8, 2017 · 1 comment

Comments

@WegDamit
Copy link

WegDamit commented Sep 8, 2017

It seems the callback
R(RscriptName) .data({foo: bar} ) .call(callbackRscript)
then callbackRscript seems to be called for each line of R output.
I'd expected the callback is called once R is done and then with one parameter with all the lines from R output.

@amcereijo
Copy link

@joshkatz

Hi,
I was trying to run a R script using call(..) and it doesn't work well because of its implementation.

R.prototype.call = function(_opts, _callback) {
  var callback = _callback || _opts;
  var opts = _.isFunction(_opts) ? {} : _opts;
  this.options.env.input = JSON.stringify([this.d, this.path, opts]);
  var child = child_process.spawn("Rscript", this.args, this.options);
  child.stderr.on("data", callback);
  child.stdout.on("data", function(d) {
    callback(null, JSON.parse(d));
  });
};

The spawn method runs asynchronously and should listen for events data and close.
With data you get any output produced by the running script and with close, you know the execution is over.

In the implementation, the events data on stderr and stdout are calling to the callback in the very first output produced by the running script instead of cache the data and return it when the execution is over.

Many R script write "debug" or "warning" data during its execution. In my case, for example I can see things like

Attaching package: 'lubridate'

The following object is masked from 'package:base':

    date


Attaching package: 'data.table'

The following objects are masked from 'package:lubridate':

    hour, isoweek, mday, minute, month, quarter, second, wday, week,
    yday, year

So the implementation should change to wait for the close event.
A suggested changed implementation could be:

function getReturnData(d) {
  try{
    return JSON.parse(d);
  } catch(err) {
    return d;
  }
}

R.prototype.call = function(_opts, _callback) {
  var callback = _callback || _opts;
  var opts = _.isFunction(_opts) ? {} : _opts;
  this.options.env.input = JSON.stringify([this.d, this.path, opts]);
  var child = child_process.spawn("Rscript", this.args, this.options);
  var errData = '';
  var outData = '';

  child.stderr.on("data", function(d) {
    errData += d;
  });

  child.stdout.on("data", function(d) {
    outData += d;
  });

  child.on('close', (code) => {
    if(errData) {
      callback(getReturnData(errData));
    } else {
      callback(null, getReturnData(outData));
    }
  });
};

I was trying that implementation and the R scripts run async with no problems.

I could make an Pull Request if you prefer.

Regards,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants