Hi Meteor team,
In pre-3.x versions, it’s documented and confirmed that async
methods implicitly call this.unblock()
, meaning multiple method calls from the same client can run concurrently.
In Meteor 3.x (which no longer uses Fibers), does this behavior still apply?
Specifically:
- If I define a method like
async myMethod(...)
, will Meteor automatically allow the next method from the same client to run concurrently?
- If so, is the only way to preserve strict sequential execution to define the method as a non-async function and use
Promise.await(...)
inside?
I’m building a system where clients can go offline and replay queued Meteor.call()
calls upon reconnect, and I need to guarantee these method calls are processed in strict order on the server side.
Would appreciate official clarification. Thanks!
Yes, all methods are async and run non-blocking and if you need a sequence you can await the result and use the result into another method. You experience async in 2 main areas (but not only): DB calls and method calls.
What I find to work best with the client side (method calls):
Meteor.callAsync('method', {})
.then(res => {
Meteor.callAsync('anotherMethod',{})
.then(...)
.catch(err => ....)
}
.catch(err => ....)
})
I think others prefer try-catch and again and I think you can also await as below.
const firstResult = await Meteor.callAsync('method', {}).then(res => res) // the final return is the return of the 'await'
const secondResults = await ... // on something depending on the first result.
For DB calls, the same thing. You can ‘fire and forget’ or preserve strict sequential execution like this
'methodName': async () => {
Collection.insertAsync({...}) // will eventually do the insert, no questions asked, no assurance.
const { _id } = await Collection.insertAsync({ ... })
const result = // ... a function that dependends on _id from above will wait for _id to be resolved.
// You can also use Promise.all(). Example from Perplexity AI:
const userQuery = Meteor.users.findOneAsync({ _id: 'user123' });
const ordersQuery = Orders.find({ userId: 'user123' }).fetchAsync();
const productsQuery = Products.find({ category: 'electronics' }).fetchAsync()
// Execute all queries concurrently
const [user, orders, products] = await Promise.all([
userQuery,
ordersQuery,
productsQuery
]);
// Return specific result (user data) with references to other queries
return {
userProfile: user, // Using result from first query
orderCount: orders.length,
featuredProducts: products.slice(0, 3)
};
}
2 Likes