Does async method automatically unblock in Meteor 3.x?

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