Meteor: How to count some data in collection? - meteor

I've a problem to count some data in a collection. This code is not working for me. Can anyone help me?
Client code:
Template.count_status.helpers({
countcategory: function(){
return Profil.find({
status: 'Available',
category: { $in: ['PTR', 'KOM'] },
}).count();
}
});
Server Code:
Meteor.methods({
countcategory: function () {
return Profil.find().count();
}
});

Make sure you have subscribed to "profil" collection(client side). And it is published in the server code. I presume that you are not using pub/sub functions.
Make sure autopublish package is added to your package (for client side code mentioned to work).
You are not using Server code pasted above.
You can call server method using below code:
Template.count_status.helpers({
countcategory: function(){
Meteor.call('countcategory', function(err,res){
if(err){
//do something with err
}
else{
//do something with result
}
});
}
});

Related

Meteor wrapAsync

I'm trying to implement the following scenario:
1. Client calls a meteor-method.
2. Inside the meteor-method i make an HTTP-Post to a different server.
3. When the HTTP-Call is responded, the meteor method should return true and in the case an error occurs it should return false.
Here is what my meteor method looks like:
uploadUserImage: function(data_url,userid) {
asyncfnc =function(data,uid){
HTTP.post("http://localhost:2000/upload", {
data: {
"data_url": data,
"user_id": uid
}
},function(err,res){
console.log(res);
if (err){
console.log("error");
throw new Error(err.message);
}
else{
console.log("return true");
return true;
}
});
};
var waitForResult = Meteor.wrapAsync(asyncfnc);
var result = waitForResult(data_url,userid);
return result;
}
The HTTP-Call works and I also get into the Callback of the HTTP.post-function.
But on the clientside where I called the meteor-method i don't get into my callback-function. It looks like this:
Meteor.call("uploadUserImage",data_url,Session.get("newUserID"),function (err, res) {
if(err){
console.log(err);
} else {
console.log('response: ', res);
}
});
What am I doing wrong? Why is my meteor-method not returning anything?
Is everything correct with my Meteor.wrapAsync()?
Thanks for your help!
I found a solution, which does not require Meteor.wrapAsync().
var url = "http://localhost:2000/upload";
//synchronous GET
var result = Meteor.http.post(url,{
data: {
"title": "i want to upload a picture",
"data_url": data_url,
"user_id": userid
},timeout:30000});
if(result.statusCode==200) {
console.log(result);
console.log("response received.");
return result;
} else {
console.log("Response issue: ", result.statusCode);
var errorJson = JSON.parse(result.content);
throw new Meteor.Error(result.statusCode, errorJson.error);
}
This makes the HTTP-Post-Call synchronous, so there is no need to wrap async.
You are asking too much in this situation.
Meteor methods can be called synchronously, but it's not advisable if the method is doing a remote call like this.
My feeling is that you are hanging on to a procedural programming model where you want a synchronous result to 1) a call to your server, and 2) a request sent to another remote server. And you want to get a return value from your call. It doesn't work like that.
Meteor protects you to a large degree from dealing with asynchronicity, but sometimes you have to accept that a little more work is required to deal with it correctly.
So my recommendation is to use callbacks for notification.

meteorjs get data returned from server callback

In meteor im trying to insert a new document by making a Meteor.call from the client. Everything is working ok, except that I want to return the id of create document to the client, so that i can redirect to the proper url.
I have something similar to this (client):
Meteor.call('scenarioCreate', scenarioObj, function(err, response) {
if(err) {
console.warn(err);
return;
}
console.info(response);
});
On server:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
Scenarios.insert( scenarioObj, function(err, id) {
console.info("new id: "+id);
if (err) {
console.warn(err);
throw new Meteor.Error(404, 'Something went wrong');
}
return id;
});
}
});
From the server side i get the console log "new id: DDaq4aWsGf3fxG7RP", but I should get that same value on the client on the "response" value, but I always get undefined.
Can anybody explain to me why or what I am doing wrong.
Meteor.methods doesn't wait for your callback. Try this:
On server:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
var newId = Scenarios.insert(scenarioObj);
return newId;
}
});
To catch any error, use try/catch
Note: If you still want to use callback, checkout fibers/future.
Your first error is that you are returning id inside the callback for insert. That doesn't do anything. Then your second is not knowing that methods are synchronously executed. That would mean that you could only use the information available inside the callback using Meteor.wrapAsync. But that's besides the point. The insert function returns the new _id. Meaning you can do this:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
return Scenarios.insert( scenarioObj );
}
});

Get Meteor Method Return Value Inside Helper Function

I have the following in server/functions.js file:
Meteor.methods({
checkIfVoted: function (postId) {
if (postId) {
...
if (condition is met) {
return true;
} else {
return false;
}
}
}
});
And then the following in client/showPost.js:
Template.showPost.helpers({
alreadyVotedByUser: function () {
var answer = false;
if(this) {
Meteor.call("checkIfVoted", this._id, function(err, response) {
if (response) { console.log(response); }
answer = response;
});
}
console.log(answer);
return answer;
}
});
When I am doing the console.log for response I get the value to be true when the condition is met, but the answer variable does not take it, and still shows as having false as its value.
(I am aware that I put the Meteor methods in the server directory and not in a common directory to be shared between client and server to provide latency compensation)
Please if some one could help me with this, it will be highly appreciated.
On the client, Meteor.call is asynchronous - it returns undefined and its return value can only be accesses via a callback. Helpers, on the other hand, execute synchronously. See the answers to this question for how you can call methods from helpers. Here's a quick solution:
$ meteor add simple:reactive-method
Template.showPost.helpers({
alreadyVotedByUser: function () {
return ReactiveMethod.call('checkIfVoted', this._id);
}
});
The problem with this package is that it can encourage bad behavior, but it should be fine for method calls which don't change state.
Also see the section about helpers in this post.

Reading Files Asynchronously on Meteor

I am very new to Meteor so if my apologies if this is a dumb question:
How do you read a file from the filesystem on the server side, and get those contents displayed on the client side. Doing it synchonously isn't a problem because I can return it right away but as I understand from reading that defeats the purpose of Meteor so I am trying to do it asynchronously. However I dont know how to connect the client/server in this fashion. Publish/Subscribe seem to only be for db collections and not filesystem files. Any guidance you can give me would be very much appreciated.
if (Meteor.isClient) {
Template.body.helpers({
myfile: function(){
return file_contents;
}
});
}
if (Meteor.isServer) {
Meteor.methods({
myfile: function(){
var fs = Npm.require("fs");
fs.readFile('/opt/SI/SIAgent/conf/myfile','utf-8', function (err, data) {
file_contents = data;
});
}
});
}
You have to use Meteor.wrapAsync to turn Node.JS fs.readFile into synchronous-looking code so that you can return the result within the Meteor method.
var fs=Npm.require("fs");
fsReadFileSync=Meteor.wrapAsync(fs.readFile,fs);
Meteor.methods({
getMyFileContent:function(){
return fsReadFileSync("/opt/SI/SIAgent/conf/myfile","utf-8");
}
});

wrapAsync + method + session

i'm having issues with wrapAsync + method + sessions.
How do I implement the WrapAsync correctly?
I want, in a template to know if the user has at least one item created by him. And then define whether or not he can create another item.
Now i'm getting this error:
W20141013-15:04:43.237(-3)? (STDERR) Error: Can't wait without a fiber
But, I could not find Fiber at Documentation. And for implementing this, is it really necessary?
 
On the client side I want something like:
//pagina.js
Template.pagina.helpers{
userHasItem: return Session.get('userHasItem');
}
//pagina.js
Meteor.call('userHasItem', Meteor.userId(), function (error,result) {
Session.set('userHasItem', result);
});
//at server side:
if(Meteor.isServer){
Meteor.startup(function () {
var userHasItemAsync = function (userId) {
setTimeout(function () {
if (Items.findOne({'userId': userId})) {
return true;
} else {
return false;
}
}, 4000);
};
Meteor.methods({
userHasItem: function(userId) {
var userHasItemSync = Meteor.wrapAsync(userHasItemAsync),
result;
try {
userHasItemSync(userId);
console.log(result);
return result;
}catch (e) {
console.log('erreur', e.message);
throw new Meteor.Error(500, e);
}
},
}
});
}
Can't get your error to reproduce based on the existing code.
Still, userHasItemAsync is not available because you've defined it locally in the Meteor.startup function. But the error you should get in this case is userHasItemAsync is undefined.
Also the code you've entered here has multiple errors (i guess you typed it in not copy / pasted from your project): template instead of Template, Template it's defined outside of isClient (probably it's in a file available for the client) etc. Because of that it's hard to reproduce your exact case.
There is no need to call a server method to see if the item exists (assuming you have set up the proper publications/subscriptions), nor any need to call wrapAsync. In fact, what you want to achieve doesn't even require a session. All of the code can be ultimately distilled to this:
Template.pagina.helpers{
userHasItem: return Items.find({ userId: Meteor.userId() }).count() > 0;
}
The cursor returned by Items.find is reactive in itself, so there is no need for using a Session.

Resources