我正在尝试通过服务器端路由使用 Meteor 访问 Rserve 服务器以调用 R 代码。允许访问 Rserve 的 Node.js 模块是 node-rio 我在 meteorhacks:npm Meteor 包中使用了 Async.wrap 函数来包装"评估"方法。当我尝试在浏览器中访问路由路径"/rio"时,我得到"1"写入控制台日志,这对于评估 R 中的命令"1"是正确的,但 Chrome 挂起并显示消息"等待本地主机"。它不会继续到下一行,并且永远不会显示"结果:1"。消息"net::ERR_EMPTY_RESPONSE最终出现在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"有一个回调函数参数,但它被包装在一个选项参数中并访问:
rio.evaluate(R_COMMAND, {callback: CALLBACK_FUNCTION})
两个错误:
- 正如您已经注意到的,Rio 希望回调作为参数中回调字段的值,而不是参数本身中的直接值。
- 您的结果 ("1") 实际上不是有效的 JSON。
这有效:
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'
});
这个答案将产生'packageVersion("base")'的预期结果,它使用节点模块rserve-client而不是rio连接到Rserve。路由还处理参数"pkg"。这是StackOverflow的问题,它为我指明了正确的方向:
如何从 Meteor 自己的回调调用异步方法?
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));
}
});