javascript - tutorial - que es meteor js
"El código de Meteor siempre debe ejecutarse dentro de una Fiber" cuando se llama a Collection.insert en el servidor (3)
Tengo el siguiente código en 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);
});
Básicamente, está extrayendo algunos datos de un feed JSON e intentando insertarlos en una colección.
Cuando inicio Meteor, obtengo la siguiente excepción;
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
No estoy muy seguro de lo que significa ese error. ¿Alguien tiene alguna idea o puede sugerir un enfoque diferente?
Como se mencionó anteriormente, es porque su código de ejecución dentro de una devolución de llamada.
Cualquier código que esté ejecutando en el lado del servidor debe estar dentro de un Fiber.
Intenta cambiar tu función getServices para que se vea así:
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();
}
Me encontré con un problema similar y esto funcionó para mí. Lo que tengo que decir es que soy muy nuevo en esto y no sé si así es como debe hacerse esto.
Probablemente pueda salirse con la suya solo al incluir su declaración de inserción en Fiber, pero no estoy seguro.
Según mis pruebas, debe envolver el inserto en el código que probé, que es similar al ejemplo anterior.
Por ejemplo, hice esto y aún falló con el error Fibras.
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();
}
}
Hice esto y funcionó bien sin errores.
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?
}
}
);
}
}
Pensé que esto podría ayudar a otros a enfrentar este problema. Todavía no he probado llamar al tipo de servicio externo asynchy después del código interno y envolverlo en un Fiber. Eso también valdría la pena probarlo. En mi caso, necesitaba saber la acción remota que sucedió antes de realizar mi acción local.
Espero que esto contribuya a este hilo de preguntas.
Solo envolver su función en una Fiber podría no ser suficiente y puede llevar a un comportamiento inesperado.
La razón es que, junto con Fiber, Meteor requiere un conjunto de variables asociadas a una fibra. Meteor utiliza datos adjuntos a una fibra como un alcance dinámico y la forma más fácil de usarlo con una API de terceros es utilizar 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''); }));
Mira estos videos con la mente despierta si quieres saber más: https://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor-what-is-meteor-bindenvironment