I am trying to call _.each function in meteor server method .
As you know the each method has a function that will be executed for each item in the list
My problem that I can’t use the bindenviroment function in a correct way
I have the below error
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
Here is my code
'fillSampleData': function() {
var fs = require('fs');
var base = process.env.PWD
projectsCollction.remove({});
changeSetsCollction.remove({});
var readFileAndInsert = function() {
fs.readFile(base + '/server/json/projects.json', 'utf8',
function(err, data) {
if (err) throw err;
console.log(data);
var json = JSON.parse(data);
//loop th
_.each(json, Meteor.bindEnvironment((eer, projctItem) => {
var project_Id = projectsCollction.insert(
projctItem)
console.log(`projict ${project_Id}`);
}));
}
//----------------------------
);
}
readFileAndInsert()
}
=============Edit=======
I have changed the code but the same result
'fillSampleData': function() {
var fs = require('fs');
var base = process.env.PWD
projectsCollction.remove({});
changeSetsCollction.remove({});
var myFunction = function(passedItem) {
Meteor.bindEnvironment((eer, passedItem) => {
var project_Id = projectsCollction.insert(
passedItem)
console.log(`project ${project_Id}`);
})
}
var readFileandInsert = function() {
fs.readFile(base + '/server/json/projects.json', 'utf8',
function(err,
data) {
if (err) throw err;
console.log(data);
var json = JSON.parse(data);
_.each(json, (item) => {
myFunction(item);
});
}
//----------------------------
);
}
readFileandInsert();
}
the error stack is
W20161022-07:22:26.840(3)? (STDERR) /home/mohammed/poly/synthesis- demo/.meteor/local/build/programs/server/packages/meteor.js:1060
W20161022-07:22:26.844(3)? (STDERR) throw new Error("Meteor code must always run within a Fiber. " +
W20161022-07:22:26.848(3)? (STDERR) ^
W20161022-07:22:26.853(3)? (STDERR)
W20161022-07:22:26.855(3)? (STDERR) Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
W20161022-07:22:26.860(3)? (STDERR) at Object.Meteor._nodeCodeMustBeInFiber (packages/meteor/dynamics_nodejs.js:9:1)
W20161022-07:22:26.863(3)? (STDERR) at Object.Meteor.bindEnvironment (packages/meteor/dynamics_nodejs.js:85:1)
W20161022-07:22:26.865(3)? (STDERR) at myFunction (server/main.js:42:14)
W20161022-07:22:26.867(3)? (STDERR) at server/main.js:56:13
W20161022-07:22:26.868(3)? (STDERR) at arrayEach (/home/mohammed/poly/synthesis-demo/node_modules/lodash/lodash.js:451:11)
W20161022-07:22:26.870(3)? (STDERR) at Function.forEach (/home/mohammed/poly/synthesis-demo/node_modules/lodash/lodash.js:8634:14)
W20161022-07:22:26.872(3)? (STDERR) at server/main.js:55:13
W20161022-07:22:26.873(3)? (STDERR) at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)
_.each will only pass the element to the function, you are trying to pass two. You'll need to use a function to do it
_.each(json,(item) => {
myFunction(item);
});
and declare this function:
var myFunction = function(passedItem) {
Meteor.bindEnvironment((eer, passedItem) => {
var project_Id = projectsCollction.insert(
passedItem)
console.log(`projict ${project_Id}`);
})
}
I found that the bindEnvironment function was in a wrong place
fs.readFile(base + '/server/json/projects.json', 'utf8',
Meteor.bindEnvironment(function(err,
data) {
if (err) throw err;
console.log(data);
var json = JSON.parse(data);
_.each(json, (item) => {
var project_Id = projectsCollction.insert(
item)
console.log(`project ${project_Id}`);
});
})
Related
I am having trouble with getting return value from wrapAsync function in meteor. Below is my code
Template.greet.helpers({
greet : function () {
var convertAsyncToSync = Meteor.wrapAsync( HTTP.get );
resultOfAsyncToSync = convertAsyncToSync('http://www.demo.com/api/greet', {} );
console.log(resultOfAsyncToSync);
return resultOfAsyncToSync;
}
});
I get undefined value in console.
try
Template.greet.onCreated(function(){
this.apiResult = new ReactiveVar(null);
})
Template.greet.helpers({
greet : function () {
var t = Template.instance();
HTTP.get('http://www.demo.com/api/greet', {}, function(e,r){
//process response and save it in reactivevar
t.apiResult.set(r.data);
});
return t.apiResult.get();
}
});
don't forget to add package meteor add reactive-var
EDIT
Template.greet.onRendered(function(){
var t = Template.instance();
HTTP.get('http://www.demo.com/api/greet', {}, function(e,r){
//process response and save it in reactivevar
t.apiResult.set(r.data);
});
})
Template.greet.helpers({
greet : function () {
var t = Template.instance();
return t.apiResult.get();
}
});
This is weird but when I call a external function from Meteor.method function it will always return undefined in the client I tried Meteor.wrapAsync but I think I'm doing something wrong. Here is my code:
var demoFunction = function () {
//database operations
var user = this.userId;
if (!user)
return;
var count = Users.aggregate([
{ $group: {_id: null, count: {$sum: 1}} }
]);
if (count[0] && count[0].count)
return count[0].count;
return 0;
}
Meteor.methods({
// NOT WORKING, How can I make this work?
methodDemo: function () {
var result = demoFunction ();
return result;
},
// Works
methodDemo2: function () {
//database operations
var user = this.userId;
if (!user)
return;
var count = Users.aggregate([
{ $group: {_id: null, count: {$sum: 1}} }
]);
if (count[0] && count[0].count)
return count[0].count;
return 0;
}
});
// Call from client
Meteor.call("methodDemo", function (err, res) { });
calling external functions doesn't work the same way if I put the code inside the meteor method why?
Try using Meteor.userId() in your function instead of this.userId. I think you are loosing the value of this when calling your function causing it to exit early.
Since you declared the function with a var it is scoped outside of methodDemo().
You could declare the function globally by removing var or move the demoFunction() code into methodDemo().
I am trying to use Restivus to expose a get route to return a specific document by its serial number.
Basic code:
// lib/router.js
Router.onBeforeAction(requireLogin, {
except: ['auth', 'api']
});
// server/restivus.js
Meteor.startup(function() {
Restivus.configure({
useAuth: false,
prettyJson: true
});
});
// lib/collection/schedule.js
if (Meteor.isServer) {
Restivus.addRoute('schedules/:serial', {authRequired: false}, {
get: function() {
var schedule = Schedules.findOne({collector: this.urlParams.serial});
if (schedule) {
return {status: 'success', data: schedule};
}
}
});
}
Complete log error:
curl -X GET http://localhost:3000/api/schedules/00000020
Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
at Object.Meteor.userId (packages/accounts-base/accounts_server.js:19:1)
at [object Object].requireLogin (app/lib/router.js:85:15)
at packages/iron:router/lib/router.js:277:1
at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1)
at [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1)
at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1)
at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1)
at packages/meteor/dynamics_nodejs.js:121:1
at [object Object].dispatch (packages/iron:middleware-stack/lib/middleware_stack.js:275:1)
at [object Object].RouteController._runRoute (packages/iron:router/lib/route_controller_server.js:63:1)
I solved adding !Meteor.isServer at hook onBeforeAction:
var requireLogin = function() {
if (!Meteor.isServer && !Meteor.userId() && !Meteor.loggingIn()) {
this.redirect('auth');
} else {
this.next();
}
};
Router.onBeforeAction(requireLogin, {
except: ['auth']
});
I am using jasmine to test the features of redis. As the redis APIs are all asynchronized call, I don't know how to test the result with jasmine expect().toBe(). I always see the error:
throw err;
^
TypeError: Cannot call method 'expect' of null
Here is my test code:
var redis = require('redis');
describe("A suite for redis", function() {
var db = null;
beforeEach(function() {
db = redis.createClient();
// if you'd like to select database 3, instead of 0 (default), call
// db.select(3, function() { /* ... */ });
db.on("error", function (err) {
console.log("Error " + err);
});
});
afterEach(function() {
db.quit();
});
it('test string', function(){
db.set('str_key1', 'hello', redis.print);
db.get('str_key1', function(err,ret){
expect(ret).toBe('hello');
});
});
});
For synchronized call, may use Jasmine asynchronous feature, passing a done() to beforeEach() and it(), see:
http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support
So, your code can be changed to:
var redis = require('redis');
describe("A suite for redis", function() {
var db = null;
beforeEach(function(done) {
db = redis.createClient();
// if you'd like to select database 3, instead of 0 (default), call
// db.select(3, function() { /* ... */ });
db.on("error", function (err) {
console.log("Error " + err);
});
done();
});
afterEach(function(done) {
db.quit();
done();
});
it('test string', function(done){
db.set('str_key1', 'hello', redis.print);
db.get('str_key1', function(err,ret){
expect(ret).toBe('hello');
done(); // put done() after expect(), or else expect() may report error
});
});
});
expect(val).toBe('hello');
I don't see "val" is defined in above code, you may want to check "ret".
expect(ret).toBe('hello');
Within a function that is already within Meteor.binEnvironment, when I run <collection>.find ({}), I get the error throw new Error ('Can \' t wait without a fiber ');
If you place that call also within Meteor.bindEnvironment(<collection>.find ({})), the error message becomes: throw new Error (noFiberMessage);
The function in question runs through Meteor.methods ({})
Where am I going wrong?
Example to reproduce the error:
Meteor.methods({
"teste" : Meteor.bindEnvironment(function(){
var Future = Meteor.require('fibers/future');
var future = new Future();
setTimeout(function(){
return future.return(Sessions.findOne({}))
}, 15000);
console.log('fut', future.wait());
})
});
Try using Meteor._wrapAsync instead.
This is an example of an async function, but any other would do:
var asyncfunction = function(callback) {
Meteor.setTimeout(function(){
callback(null, Sessions.findOne({}))
}, 15000);
}
var syncfunction = Meteor._wrapAsync(asyncfunction);
var result = syncfunction();
console.log(result);
You could wrap any asynchronous function and make it synchronous and bind the fibers with it this way.
I could not apply the suggested solution in my project, currently do this way:
Meteor.methods({
"teste" : Meteor.bindEnvironment(function(){
var Fiber = Meteor.require('fibers');
var Future = Meteor.require('fibers/future');
var future = new Future();
setTimeout(function(){
return future.return(
Fiber(function(){
Sessions.findOne({});
}).run()
);
}, 15000);
console.log('fut', future.wait());
})
});