Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get an async data in a function with Meteor

I'm a newbie with Meteor and I'm trying to get an async data from the Heroku API.

Server side code:

heroku = Meteor.require("heroku");

Meteor.methods({
    'getHeroku': function getHeroku(app){
        client = new heroku.Heroku({key: "xxxxxx"});
        client.get_app(app, function (error, result) {
            return result;
        });
    }
});

Client side code:

Template.herokuDashboard.helpers({
    appInfo: function() {
        Meteor.call('getHeroku', "meathook-api", function (error, result) {
            console.warn(result);
        } );
    }
});

Heroku takes a while to answer so the answer is undefined.

So what is the best way to catch the async result?

Thank you.

like image 472
skozz Avatar asked Jul 14 '14 18:07

skozz


1 Answers

General solution :

Client Side:

    if (Meteor.isClient) {
        Template.herokuDashboard.helpers({
            appInfo: function() {
                return Session.get("herokuDashboard_appInfo");
            }
        });
        Template.herokuDashboard.created = function(){
            Meteor.call('getData', function (error, result) {
                Session.set("herokuDashboard_appInfo",result);
            } );
        }
    }

There is no way to directly return results from Meteor.call. However there are at least 2 solutions (@akshat and @Hubert OG): How to use Meteor methods inside of a template helper

Server Side (Meteor._wrapAsync):

Using Meteor._wrapAsync :

if (Meteor.isServer) {
  var asyncFunc = function(callback){
      setTimeout(function(){
          // callback(error, result);
          // success :
          callback(null,"result");
          // failure:
          // callback(new Error("error"));
      },2000)
  }
  var syncFunc = Meteor._wrapAsync(asyncFunc);
  Meteor.methods({
      'getData': function(){
          var result;
          try{
               result = syncFunc();
          }catch(e){
              console.log("getData method returned error : " + e);
          }finally{
              return result;
          }

      }
  });
}

Proper usage of Future library:

if (Meteor.isServer) {
    Future = Npm.require('fibers/future');

    Meteor.methods({
        'getData': function() {
            var fut = new Future();
            setTimeout(
                Meteor.bindEnvironment(
                    function() {
                        fut.return("test");
                    },
                    function(exception) {
                        console.log("Exception : ", exception);
                        fut.throw(new Error("Async function throw exception"));
                    }
                ),
                1000
            )
            return fut.wait();
        }
    });
}

Using Future library WITHOUT Meteor.bindEnvironment is NOT RECOMMENDED, see:

  • https://www.eventedmind.com/feed/meteor-what-is-meteor-bindenvironment
  • @imslavko comment from 18.07.2014
  • @Akshat answer : What's going on with Meteor and Fibers/bindEnvironment()?

There is also 3rd approach using Async utilities

like image 191
Kuba Wyrobek Avatar answered Sep 30 '22 10:09

Kuba Wyrobek