Async Meteor Method calls

jankapunkt

Jan Küster

Posted on September 17, 2020

Async Meteor Method calls

Meteor is mostly backward compatible to even < 1.0 projects. Therefore lots of code is still callback based. So is the Meteor.call method. You can easily wrap it into a Promise-based approach:

export const callMethod = ({ name, args }) => 
  new Promise((resolve, reject) => {
    Meteor.call(name, args, (error, result) => {
      if (error) {
        return reject(error)
      }

      return resolve(result)
    })
})
Enter fullscreen mode Exit fullscreen mode

Although Meteor.call supports multiple arguments I rather prefer to pass a single object with named arguments to keep the code more expressive.

You can then use callMethod natively in an async environment:

Template.myTemplate.events({
  'click .some-button': async function (event, templateInstance) {
    const age = await callMethod({
      name: 'getAge', 
      args: { name: 'John Doe' }
    })
    console.log(age) // whatever the method returned
  }
})
Enter fullscreen mode Exit fullscreen mode

Additionally you can "hook" into these calls and thus mix callbacks with promises and create a decent UX experience when method calls are part of user interactions:

export const callMethod = ({ name, args, prepare, receive, success, failure }) => {
  // before call
  if (typeof prepare === 'function') {
    prepare()
  }

  // create the promise
  const promise = new Promise((resolve, reject) => {
    Meteor.call(name, args, (error, result) => {
      // on received
      if (typeof receive === 'function') {
        receive()
      }

      if (error) {
        return reject(error)
      }

      return resolve(result)
    })
  })

  // on success
  if (typeof success === 'function') {
    promise.then(success)
  }

  // on error
  if (typeof failure === 'function') {
    promise.catch(failure)
  }

  return promise
}
Enter fullscreen mode Exit fullscreen mode

The code can then be used for example to display a "waiting" indicator:

Template.myTemplate.events({
  'click .update-button': async function (event, templateInstance) {
   const updatedDoc = await callMethod({
     name: 'updateUser', 
     args: { name: 'John Doe', age: 42 },
     prepare: () => templateInstance.state.set('updating', true),
     receive: () => templateInstance.state.set('updating', false),
     failure: er => alert(er),
     success: () => alert('updated')
   })
   // process updatedDoc if desired
})
Enter fullscreen mode Exit fullscreen mode


I regularly publish articles here on dev.to about Meteor and JavaScript. If you like what you are reading and want to support me, you can send me a tip via PayPal.

You can also find (and contact) me on GitHub, Twitter and LinkedIn.

Keep up with the latest development on Meteor by visiting their blog and if you are the same into Meteor like I am and want to show it to the world, you should check out the Meteor merch store.

💖 💪 🙅 🚩
jankapunkt
Jan Küster

Posted on September 17, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

The Renaissance of Meteor.js
javascript The Renaissance of Meteor.js

July 26, 2024

Async Meteor Method calls
javascript Async Meteor Method calls

September 17, 2020