How to make Meteor methods synchronous?

This is a very common question, being asked in various shapes and forms. Most people don't realize when they are making asynchronous calls. The solution, however, is always the same: wrap your method code on the server into a fiber or use a future.

The best practice, I think, is to use the currently available Meteor._wrapAsync function as described, e.g., here: Meteor: Calling an asynchronous function inside a Meteor.method and returning the result

Some other options are described here: https://gist.github.com/possibilities/3443021


Update: The method is now called Meteor.wrapAsync.


I followed this tutorial and do something like below

This is a meteor server side method

productIdResult:function(searchstring)
{
   {
      var skimlinks_query = Async.wrap(skimlinks.query);
      var title_val="title:\"electric bicycle\"  AND merchantCategory:*bikes*";                     
      var result = skimlinks_query({
                        searchFor: searchstring,
                        start:start,
                        rows:rows,
                        fq: "country:US"
                    });
      return result;
}

And I call it from client like this

Meteor.call('productIdResult',
            searchstring,
            function(error,resul)
            {
                arr[0]=resul.skimlinksProductAPI.products[0].title;
                $( "#op1").autocomplete({source:arr});

            }
);

Note that it is not synchronous, but you get the return value in the callback


Put the code that you want to run after the method completes into the method callback. This is standard for any asynchronous javascript.

clientFunction = function(){
  Meteor.call('serverFunction', function(err, result){
    if (err) {
      alert(err);
    } else {
      Session.set('whatever', result.whatever);
    }
  });
};

That sets the value of the session variable once the method call returns. Now you use Meteor's reactivity to use that variable:

Template.hello.helpers({
  myWhatever: function () {
    var whatever = Session.get('whatever');

    if (whatever) return whatever;

    return 'Loading whatever...';
  }
});