Using node-rio from Meteor Server Side Route

可紊 提交于 2019-12-23 02:42:33

问题


I'm trying to access an Rserve server using Meteor through a server side route to call R code. The Node.js module that allows access to Rserve is node-rio I have used the Async.wrap function in the meteorhacks:npm Meteor package to wrap the "evaluate" method. When I try to access the route path "/rio" in a browser, I get "1" written to the console log, which is correct for the evaluation of the command "1" in R, but Chrome hangs with the message "Waiting for localhost". It doesn't proceed to the next line and "Result: 1" is never shown. The message "net::ERR_EMPTY_RESPONSE eventually shows up in Chrome.

Router.route('/rio', function() {
    var rio = Meteor.npmRequire('rio');
    var evalSync = Async.wrap(rio, 'evaluate');
    var result = evalSync('1');
    console.log("Result: " + result);

    // JSON
    this.response.writeHead(200, {'Content-Type': 'application/json'});
    this.response.end(result);
}, {
    where: 'server'
});

"evaluate" has a callback function parameter, but it is wrapped in an options parameter and accessed:

rio.evaluate(R_COMMAND, {callback: CALLBACK_FUNCTION})

回答1:


Two errors:

  1. as you already noted rio expects the callback as a value to the callback field in the parameters, not straight in the arguments themselves.
  2. your result ("1") wasn't actually valid JSON.

This works:

Router.route('/rio', function() {                                               
    var rio = Meteor.npmRequire('rio');                                         
    var evalSync = Async.wrap(function(exp, callback) {                         
        rio.evaluate(exp, {callback: callback});                                
    });                                                                         
    var result = evalSync('1');                                                 
    console.log("Result: " + result);                                           

    // JSON                                                                     
    this.response.writeHead(200, {'Content-Type': 'application/json'});         
    this.response.end(JSON.stringify({result: result}));                        
}, {                                                                            
    where: 'server'                                                             
});



回答2:


This answer will produce the expected result for 'packageVersion("base")', it uses the Node module rserve-client instead of rio to connect to Rserve. The route also handles the parameter 'pkg'. This is the StackOverflow question that pointed me in the right direction:

How to call async method from Meteor own callbacks?

Router.route('rserve', {
    path: '/rserve/:pkg',
    where: 'server',
    action:  function() {
        var r = Meteor.npmRequire("rserve-client");
        var Future = Meteor.npmRequire("fibers/future");
        var fut = new Future();

        var cmd = 'packageVersion("' + this.params.pkg + '")';

        var callR = function (input) {
            r.connect('127.0.0.1', 6311, function (err, client) {
                client.evaluate(input, function (err, ans) {
                    console.log("Result: " + ans);
                    client.end();

                    fut.return(ans);
                });
            });

            return fut.wait();
        };

        var result = callR(cmd);

        this.response.writeHead(200, {'Content-Type': 'application/json'});
        this.response.end(JSON.stringify(result));
    }
});


来源:https://stackoverflow.com/questions/28163016/using-node-rio-from-meteor-server-side-route

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!