在服务器上调用Collection.insert时,“Meteor代码必须始终在Fibre中运行”

我有以下代码在server / statusboard.js;

var require = __meteor_bootstrap__.require, request = require("request") function getServices(services) { services = []; request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) { var resJSON = JSON.parse(body); _.each(resJSON, function(data) { var host = data["host_name"]; var service = data["service_description"]; var hardState = data["last_hard_state"]; var currState = data["current_state"]; services+={host: host, service: service, hardState: hardState, currState: currState}; Services.insert({host: host, service: service, hardState: hardState, currState: currState}); }); }); } Meteor.startup(function () { var services = []; getServices(services); console.log(services); }); 

基本上,它是从JSON提要中提取一些数据并尝试将其推送到一个集合中。

当我启动meteor,我得到以下例外;

 app/packages/livedata/livedata_server.js:781 throw exception; ^ Error: Meteor code must always run within a Fiber at [object Object].withValue (app/packages/meteor/dynamics_nodejs.js:22:15) at [object Object].apply (app/packages/livedata/livedata_server.js:767:45) at [object Object].insert (app/packages/mongo-livedata/collection.js:199:21) at app/server/statusboard.js:15:16 at Array.forEach (native) at Function.<anonymous> (app/packages/underscore/underscore.js:76:11) at Request._callback (app/server/statusboard.js:9:7) at Request.callback (/usr/local/meteor/lib/node_modules/request/main.js:108:22) at Request.<anonymous> (/usr/local/meteor/lib/node_modules/request/main.js:468:18) at Request.emit (events.js:67:17) Exited with code: 1 

我不太确定那个错误是什么意思。 有没有人有任何想法,或可以build议一个不同的方法?

如上所述,这是因为您在callback中执行的代码。

您在服务器端运行的任何代码都需要包含在光纤中。

尝试改变你的getServices函数看起来像这样:

 function getServices(services) { Fiber(function() { services = []; request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) { var resJSON = JSON.parse(body); _.each(resJSON, function(data) { var host = data["host_name"]; var service = data["service_description"]; var hardState = data["last_hard_state"]; var currState = data["current_state"]; services+={host: host, service: service, hardState: hardState, currState: currState}; Services.insert({host: host, service: service, hardState: hardState, currState: currState}); }); }); }).run(); } 

我遇到了类似的问题,这对我有用。 我不得不说的是,我对这个很陌生,我不知道这是否应该这样做。

你可能只能把你的插入语句包装在Fibre中,但是我并不积极。

只是将你的function封装在光纤中可能不够,并可能导致意外的行为。

原因是,与Fibre一起,Meteor需要一组连接到光纤的variables。 Meteor使用附加在光纤上的数据作为dynamic范围,使用第三方api最简单的方法是使用Meteor.bindEnvironment

 T.post('someurl', Meteor.bindEnvironment(function (err, res) { // do stuff // can access Meteor.userId // still have MongoDB write fence }, function () { console.log('Failed to bind environment'); })); 

如果您想了解更多信息, 请观看以下video: https : //www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor-什么-是-meteorbindenvironment

根据我的testing,您必须将插入代码包装在我testing过的代码中,与上例相似。

例如,我这样做,它仍然失败,纤维错误。

 function insertPost(args) { if(args) { Fiber(function() { post_text = args.text.slice(0,140); T.post('statuses/update', { status: post_text }, function(err, reply) { if(reply){ // TODO remove console output console.log('reply: ' + JSON.stringify(reply,0,4)); console.log('incoming twitter string: ' + reply.id_str); // TODO insert record var ts = Date.now(); id = Posts.insert({ post: post_text, twitter_id_str: reply.id_str, created: ts }); }else { console.log('error: ' + JSON.stringify(err,0,4)); // TODO maybe store locally even though it failed on twitter // and run service in background to push them later? } } ); }).run(); } } 

我这样做,没有错误,运行良好。

 function insertPost(args) { if(args) { post_text = args.text.slice(0,140); T.post('statuses/update', { status: post_text }, function(err, reply) { if(reply){ // TODO remove console output console.log('reply: ' + JSON.stringify(reply,0,4)); console.log('incoming twitter string: ' + reply.id_str); // TODO insert record var ts = Date.now(); Fiber(function() { id = Posts.insert({ post: post_text, twitter_id_str: reply.id_str, created: ts }); }).run(); }else { console.log('error: ' + JSON.stringify(err,0,4)); // TODO maybe store locally even though it failed on twitter // and run service in background to push them later? } } ); } } 

我认为这可能会帮助别人遇到这个问题。 我还没有testing过在内部代码之后调用外部服务的asynchytypes,并将其封装在一个光纤中。 这也许值得一试。 就我而言,我需要知道在执行本地操作之前发生的远程操作。

希望这有助于这个问题的线程。