Как получить асинхронные данные в функции с Meteor

Я новичок в Meteor, и я пытаюсь получить асинхронные данные из API Heroku.

Код на стороне сервера:

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;
        });
    }
});

Клиентский код:

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

Героку требуется время, чтобы ответить, поэтому ответ undefined.

Итак, какой лучший способ поймать результат async?

Спасибо.

Ответ 1

Общее решение:

Сторона клиента:

    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);
            } );
        }
    }

Невозможно вернуть напрямую результат Meteor.call. Однако есть как минимум 2 решения (@akshat и @Hubert OG): Как использовать методы Meteor внутри помощника шаблона

Сторона сервера (Meteor._wrapAsync):

Использование 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;
          }

      }
  });
}

Правильное использование библиотеки Future:

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();
        }
    });
}

Использование будущей библиотеки БЕЗ Meteor.bindEnvironment НЕ РЕКОМЕНДУЕТСЯ, см.

Существует также 3-й подход с использованием Утилиты Async