I've never took the time/chance to really understand the scope of Deps.autorun... so here I am again with the same problem that had bothered me many times (previously, I always found a workaround and bypass the issue)... anyways, basically, I have a function defined on the server side:
serverFunc = function() {}
and on the client side, I do
Deps.autorun(function() { var test = serverFunc(); }
I get error message say serverFunc is not defined.
Can someone kindly help me understanding why this is happening?
Thanks so much!
Deps.autorun() always runs once, then reruns the function whenever any of the dependencies that are tracked changes. These dependencies usually need to be set up as Meteor reactive data sources. A simple function being undefined on the client and then defined on the server isn't enough to retrigger.
If you want functions defined only on the server to be called from the client, you have to do two things:
On the server, put the function in Meteor.methods
On the client, use Meteor.call
Otherwise, a function defined only on the server does not exist on the client, and calling it on the client will throw an error as calling an undefined function.
Related
I am building a Meteor application with some custom authentication in addition to the built-in accounts MDG package.
I want to have a function I call at the front of Meteor methods to verify authentication. If authentication fails, I would like to do the equivalent of PHP's die() function - return a message and stop execution.
I could always do something like this: if(!checkAuth()) return "Not Authenticated", however it would be nice if I could just do checkAuth() and that function takes care of stopping execution if correct permissions are not met.
Is there a way to do this?
The easy way is to throw a new Meteor.Error. If not caught it will stop the currently running function, and if it is thrown from a method or a subscription it will appear on the client-side.
function checkAuth(user) {
if(!isAuthenticated(user)) {
throw new Meteor.Error('not-authenticated', 'Users need to be authenticated to do foo')
}
}
The above thrown error server-side will appear on the client with the reason and the details. It allows you to do custom error handling tailored to whatever is happening. If any other kind of error is thrown, it will appear as "500 Internal server error".
Note that this mechanism is similar to check. You could even use a custom Match pattern :
check(user, MyPatterns.authenticatedUser)
basically I have:
Meteor.startup(function () {
"use strict";
Meteor.publish("uTree", function () {
return utree.find({});
});
});
so the question is should I wait or not for the system is up and running to start publishing? is any advantage of using Meteor.startup() in here?
short answer
The startup callback is unnecessary in this case.
long answer
The only reason you'd wrap a publisher in a startup callback is out of concern that some part of the server code (a package, collection, etc.) had not yet been evaluated.
In order for a publish function to be activated, there needs to exist a connected client making the request. In order for a connected client to exist, the server must already be running. If the server is already running, it has already evaluated all of its scripts.
Therefore, the startup callback is unnecessary in this case. Q.E.D.
I am trying to implement some methods for a DDP API, for use with a C# remote client.
Now, I want to be able to track the connection to implement some type of persistent session, to this end, id hope to be able to use the session id given by DDP on connection, example:
{
"msg": "connected",
"session": "CmnXKZ34aqSnEqscR"
}
After reading the documentation, I see that inside meteor methods, I can access the current connection using "this.connection", however, I always get an undefined "this.connection".
Was it removed? If so, how can i access it now?
PS: I dont want to login as a user and access this.userId, since the app I want to create should not login, but actually just get a document id and do work associated with that, including changes to other collections, but all, regarding ONLY this id, and I dont want to have to include this id every time I call a function, since, this could possibly lead security problems if anyone can just send any id. The app would ideally do a simple login, then associate token details with his "session".
Changing from:
() => { this.connection; }
to:
function() { this.connection; }
solves the problem from me. Based on a comment in the accepted answer.
The C# client on github has a few bugs with it as it doesn't follow the DDP spec exactly. When you send commands to it to connect and run a call, it usually sends the '.call' too soon.
The method does work if you do it this way with this.connection on the server side Meteor method.
You need to make sure you send the method calls after you know that you are actually connected. This is what works at least with Meteor 0.8.2
I was using a file named ".next.js" to force meteor to use the newest unsupported javascript spec using a package.
Somehow this messed it up. Changed back to default javascript and it now works.
Thank you :)
init.coffee
Meteor.startup ->
# client init
if Meteor.isClient
Meteor.call "init"
methods.coffee
Meteor.methods
init: ->
console.log #connection.httpHeaders.host
it's that easy...
If, as part of a single Meteor.call, I make two calls to the database on the server, will these happen synchronously or do I need to use a callback?
Meteor.methods({
reset: function(id) {
Players.remove(_id:id);
// Will the remove definitely have finished before the find?
Players.find();
...
}
From the docs:
In Meteor, your server code runs in a single thread per request, not in the asynchronous callback style typical of Node. We find the linear execution model a better fit for the typical server code in a Meteor application.
If you read the docs on docs.meteor.com/#remove
you can find this :
Blockquote
On the server, if you don't provide a callback, then remove blocks until the database acknowledges the write and then returns the number of removed documents, or throws an exception if something went wrong. If you do provide a callback, remove returns immediately. Once the remove completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of removed documents if the remove was successful.
Blockquote
On the client, remove never blocks. If you do not provide a callback and the remove fails on the server, then Meteor will log a warning to the console. If you provide a callback, Meteor will call that function with an error argument if there was an error, or a second argument indicating the number of removed documents if the remove was successful.
So on server side you choose if you want it to run in a sync or async way, it depends if you send a callback or not.
I'm using meteor 0.6.4.
Meteor.methods({
random: function(top){
var random = Math.floor((Math.random()*(top+1)));
return random;
}
});
It returns undefined whenever I execute
Meteor.call('random', 10);
Any ideas how I can get past this?
This is a perfectly normal behavior: server method calls in Meteor are documented to be asynchronous :
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method.
It means that when you ask for a Meteor.call method to execute remotely on the server, the local method call is non blocking and returns undefined immediately.
When the method has been called on the server it will send the result asynchronously to the client, so you should retrieve it using the callback pattern :
Meteor.call("myMethod", arguments..., function(error, result){
if(error){
console.log(error.reason);
return;
}
// do something with result
});
The anonymous callback function will be called on the client as soon as the server method result is sent back to the client.
There is another subtle feature in Meteor invalidating what I just said : latency compensation and methods stubs.
In case the server method call can be SIMULATED properly in the client and thus executed right away without a round-trip to the server, you can define what is called a method stub (or simulation).
A common use case for this behavior is inserting immediately in the local (client side replication subset) database some user content just posted (a comment under a blog article for example) : all the necessary data and logic is available and it makes sense to simulate server side insertion.
What happens next is that the user sees the webpage updated as soon as he submitted his content even if the server hasn't acknowledged these changes yet. (this is an example how latency compensation is implemented in Meteor).
Of course the server has final words on what gets ultimately inserted in the database, this means that when the server side twin method is executed, its actions will take precedence and replace what was inserted in the local database.
To define such method stub, you just have to define the same server method name on client code.
If the method declaration is defined in shared code (shipped both to client and server), you can test if the method call is actually a simulation by checking the isSimulation property :
Meteor.methods({
myMethod: function(arguments...){
if(this.isSimulation){
// called from the client
}
}
});
UPDATE 26/11/2014 : #steph643 commented on how the last part of my previous answer was actually wrong, here is a correction.
Note that on the server method calls can always be invoked using the synchronous syntax because server environment provides adequate blocking mechanism (fibers).
On the client however, if you return something from a method stub, it can be executed synchronously only if you're inside another stub and you can retrieve the result in a synchronous way, ie
Meteor.methods({
intermediateMethod: function(){
return " WORLD";
},
method: function(){
var result = "HELLO";
result += intermediateResult;
var intermediateResult = Meteor.call("intermediateMethod");
return result;
}
});
This behavior is a bit weird considering that Mongo collection operations (insert/update/delete) are implemented as Meteor methods and their client versions are implementing valid stubs (modification of minimongo replicated local database subset) that can be executed synchronously.