http://docs.meteor.com/#meteor_methods
I have tried it in publish.js in my server folder.
I am successfully calling Meteor.apply and attempting the server call from the client. I always get an undefined response.
Calling Meteor.methods on the server is correct. That will define remote methods that run in the privileged environment and return results to the client. To return a normal result, just call return from your method function with some JSON value. To signal an error, throw a Meteor.Error.
On the client, Meteor.apply always returns undefined, because the method call is asynchronous. If you want the return value of the method, the last argument to apply should be a callback, which will be passed two arguments: error and result, in the typical async callback style.
Is your server code actually getting called? You can check that by updating the DB in the method and seeing if the client's cache gets the new data, or calling console.log from inside the method body and looking at the output of the "meteor" process in your terminal.
There are several places I can define my Meteor.methods() (with pro's and con's):
On the server only - when the client calls the method, it'll have to wait for the server to respond before anything changes on the client-side
On the server, and uses a stub on the client - when the client calls the method, it will execute the stub method on the client-side, which can quickly return a (predicted) response. When the server comes back with the 'actual' response, it will replace the response generated by the stub and update other elements according.
The same method on both client and server - commonly used for methods dealing with collections, where the method is actually a stub on the client-side, but this stub is the same as the server-side function, and uses the client's cached collections instead of the server's. So it will still appear to update instantly, like the stub, but I guess it's a bit more accurate in its guessing.
I've uploaded a short example here, should you need a working example of this: https://gist.github.com/2387816
I hope some will find use of this addition, and this doesn't cloud the issue that methods are primarily intended to run on the server as debergalis has explained.
Using Meteor.methods() on the client is useful too. (look for "stub" in the Meteor.call() section too...)
This allows the client to (synchronously) simulate the expected effect of the server call.
As mentioned in the docs:
You use methods all the time, because the database mutators (insert,
update, remove) are implemented as methods. (...)
A separate section explaining use of stubs on the client might ease the understanding of methods calls on the server.
Related
In LivedataConnection, line 357, there's a comment that says:
// Sends the method message to the server. May be called additional times if
// we lose the connection and reconnect before receiving a result.
Does this mean that if a client calls a method and gets disconnected before the method returns, it will re-call that message when it reconnects? What if that method isn't idempotent?
Basically, yes, as of version 1.0. Meteor methods are not idempotent. I've reported this issue, as have others, and it's basically confirmed by a core developer:
https://github.com/meteor/meteor/issues/2407#issuecomment-52375372
The best way to fix this in most cases is to try and write a unique key to the database, associating with a method request, or to make use of some other clever conditional database updates. There are some discussions about how to do that in these threads:
https://groups.google.com/d/msg/meteor-talk/j1YF7JO5Rdo/cYHR5kbhC8UJ
https://stackoverflow.com/a/26430334/586086
I've got, I think, a relatively simple question. I'm wondering in Meteor, especially when I'm defining server-side functions that I want the client to be able to call, when do I use a method vs a normal function? Why can't I just use a global function in my Meteor server code instead of defining a Meteor Method?
thanks!
Functions defined only the server are only accessible to server code (even if defined globally). So for example, if you had a function defined in server/util.js it would not be available to the client.
You could, however, define a function that was global to both the server and the client by placing it outside of the server and client directories, e.g. in lib.
Generally, you would choose to create a method over a function when you want a side effect which should only be produced on the server. Examples:
you need to sign a URL and keep the key only on the server
you need to perform a database operation that can only be done on the server (due to limitations of minimongo)
Important note - method calls from the client are asynchronous (you need to provide a callback function to know the result of the method), so that may also factor into your decision.
I'm using the samples for the AwsFlowFramework, specifically helloworld and fileprocessing. I have followed all the setup instructions given here. All the client classes are successfully created with the aspect weaver. It all compiles and runs.
But trying to do .get on a Promise within an asynchronous method doesn't work. It waits forever and a result is never returned.
What am I doing wrong?
In particular the helloworld sample doesn't have any asynchronous method nor does it attempt to do a .get on a Promise. Therefore, it does work when copied outright and I can see in the activities client the "hello world" message printed. Yet, if I create a stub Asynchronous method to call get on the Promise<Void> returned by printHello, the client of the activities is never called and so the workflow waits forever. In fact the example works if I set the returned promise to a variable. The problem only arises if I try to call .get on the Promise. The fileprocessing example which does have asynchronous methods doesn't work.
I see the workflows and the activity types being registered in my aws console.
I'm using the Java SDK 1.4.1 and Eclipse Juno.
My list of unsuccessful attempts:
Tried it with Eclipse Indigo in case the aspect weaver does different things.
Made all asynchronous methods private as suggested by this question.
If I call .isReady() on the Promise this is always false even if I call it after I see the "helloworld" message printed (made certain by having a sleep in between). This leads me to think that Promise.get blocks the caller until Promise.isReady is true but because somehow this is never true, the client is not called and the workflow waits forever.
Tried different endpoints.
My very bad. I had a misconfiguration in the aop.xml file and so the load aspectj weaving for the remote calls was not correct.
Meteor's documentation states:
In Meteor, your server code runs in a single thread per request, not in the asynchronous callback style typical of Node
Do they actually mean?
A) the server is running multiple threads in parallel (which seems unusual within the Node.js ecosystem)
or
B) There is still only a single thread within an evented server and each request is processed sequentially, at least until it makes calls to resources outside the server - like the datastore, at which point the server itself is handling the callbacks while it processes with other requests, so you don't have to write/administer the callbacks yourself.
Brad, your B is correct.
Meteor uses fibers internally. As you said, there's only one thread inside an evented server, but when you do (eg) a database read, Fibers yields and control quickly gets back to the event loop. So your code looks like:
doc = MyCollection.findOne(id);
(with a hidden "yield to the event loop, come back when the doc is here") rather than
MyCollection.findOne(id, function (err, doc) {
if (err)
handle(err);
process(doc);
});
Error handling in the fiber version also just uses standard JavaScript exceptions instead of needing to check an argument every time.
I think this leads to an easier style of code to read for business logic which wants to take a bunch of actions which depend on each other in series. However, most of Meteor's synchronous APIs optionally take callbacks and become asynchronous, if you'd like to use the async style.
I am creating a node.js module which communicates with a program through XML-RPC. The API for this program changed recently after a certain version. For this reason, when a client is created (createClient) I want to ask the program its version (through XML-RPC) and base my API definitions on that.
The problem with this is that, because I do the above asynchronously, there exists a possibility that the work has not finished before the client is actually used. In other words:
var client = program.createClient();
client.doSomething();
doSomething() will fail because the API definitions have not been set, I imagine because HTTP XML-RPC response has not returned from the program.
What are some ways to remedy this? I want to be able to have a variable named client and work with that, as later I will be calling methods on it to get information (which will be returned via a callback).
Set it up this way:
program.createClient(function (client) {
client.doSomething()
})
Any time there is IO, it must be async. Another approach to this would be with a promise/future/coroutine type thing, but imo, just learning to love the callback is best :)