Closed Marcel-Tronco closed 1 month ago
Hi @Marcel-Tronco,
There is a difference here between what the async stub is and what the async invocation is.
Let's say you have this method:
Meteor.methods({
syncMethod() {
const result = 2;
console.log(result)
return result;
}
})
Here are the two ways you can call it with Meteor.call()
:
// Case 1:
console.log(1)
Meteor.call("syncMethod")
console.log(3)
// Results:
// 1
// 2
// 3
// Case 2:
console.log(1)
Meteor.call("syncMethod", (err, res) => console.log("invocation result ", res))
console.log(3)
// Results
// 1
// 2
// 3
// invocation result 2
For the example above, the second invocation is "async", but your method ("stubs") is sync.
That's what the docs is saying in the paragraph you sent here.
The doc also specifies that Meteor.call must be used to call sync methods: "This is how to invoke a method with a sync stub."
And we also have this warning there:
However, we can use Meteor.call() to invoke an async method, as you're doing, but you'll get a promise because you're invoking an async method.
So it's not a bug. Meteor will not solve async methods and return the value. You need to await
for it.
Thanks for the explanation. That's what I figured. In the example above I only defined those methods on the server by the way, so I didn't define a client stub. The concept of the stub is a little opaque atm. It's only used at several points, but there's not too much explanation.
This is just to give you an idea what appeared unclear to me as a user:
How are stubs defined? The docs say every client invocation of a server method defines one, but that i can define one myself too. But then again, is there a situation where there would be no client stub? On some explanatory StackOverflow question stub is used for both server methods and client simulations of them. What's the difference between calling .call
(without a callback) and .callAsync
other than .callAsync
always returning a promise?
I suppose there's good reason for you to do this (probably enabling async handling in client/server comunications), but as a user I'd appreciate to know about the differences between .call
.callAsync
to not stumble into surprises.
In Meteor, stubs
are client-side simulations of server methods that make the app feel more responsive. They're only created if the method is defined on both the client and server.
This is what makes optimist-ui possible on Meteor. At this point, Meteor uses Minimongo to store the data on the client side and do its "magic".
Meteor.call
without a callback is synchronous on the server but always asynchronous on the client, while Meteor.call
with a callback and Meteor.callAsync (which returns a Promise) are always asynchronous.
is there a situation where there would be no client stub?
Yes. Stubs are created when your method calls a MongoDB write function (IF this method is declared in the client). For example:
//client
Meteor.methods({
"task.save"(task) {
return TaskCollection.insertAsync(task)
}
})
When you call task.save
(it doesn't matter if it's with .call
or .callAsync
, Meteor will consider this invocation a stub because it needs to simulate an insert in the client.
Now, if your method does not call anything MongoDB related, you don't have a stub:
Meteor.methods({
"getInfo"() {
// fetch data in some external API
return fetch(/**/)
}
})
I hope this helps you.
For now, I'm closing this issue (as it isn't a bug), but if you have more questions, feel free to leave them below 🙌
This is happening in Meteor 3.0.2 in a Debian Bookworm Docker container.
As the documentation points out we can call a async method of
Meteor.methods
on the client synchronously withMeteor.call
. The documentation points out to usecallAsnyc
to get a promise andcall
to block the results synchronously.So if we have some method like this:
We'd expect to call it in the client like this:
But instead the Json-Result still is a promise. I worked around it using it like this:
The documentation says to sync calls:
That might either mean for a async method that the promise is returned or that the server waits until the promise is resolved.
So I can't determine whether this is a bug or not. But if it's not I'd appreciate some clarification on callAsync and call distinction, especially as you have an async method yourself in the docs for the methods.