2013-11-20 3 views
5

Я сталкиваюсь с чем-то, чего я не понимаю с помощью Meteor. У меня есть этот метод, который берет запрос, отправляет его на amazon, а затем в обратном вызове этой функции я пытаюсь вернуть результаты.Возвращаемая стоимость от обратного вызова в Meteor.method

Meteor.methods({ 
    'search': function(query) { 
     var bookInfo; 
     if (Meteor.isServer) { 
      amazon.execute('ItemSearch', { 
       'SearchIndex': 'Books', 
       'Keywords': query, 
       'ResponseGroup': 'ItemAttributes' 
      }, function(results) { 
       bookInfo = results; 
       console.log(bookInfo); 
       return bookInfo; 
      }); 
     } 
    } 
}); 

Но когда я помещал следующее в консоли в браузере (хром):

Meteor.call('search', 'harry potter', function(error, response) { 
    console.log('response:', response); 
}); 

Я получаю это:

undefined 
response: undefined   VM13464:3 

Я думаю, я понимаю, что первое не определено исходит из метода, который не возвращает ничего на клиенте, но обратный вызов вообще не работает.

amazon.execute (...) определенно возвращает что-то, так как console.log прямо над возвратом регистрирует информацию, которую я ищу.

Любые идеи, что происходит не так, и как я могу это исправить?

ответ

16

Для достижения вашей цели необходимо использовать Future.

Как использовать будущее с Meteor 0.6?

Meteor.startup(function() { 
Future = Npm.require('fibers/future'); 

// use Future here 
} 

Ваш метод переписан будущего:

Meteor.methods({ 
'search': function(query) { 

    var future = new Future(); 

    amazon.execute('ItemSearch', { 
      'SearchIndex': 'Books', 
      'Keywords': query, 
      'ResponseGroup': 'ItemAttributes' 
    }, function(results) { 
     console.log(results); 

     future["return"](results) 

    }); 

    return future.wait(); 
} 
}); 

Теперь он должен работать.

Meteor.call('search', 'harry potter', function(error, response) { 
    if(error){ 
    console.log('ERROR :', error); 
    }else{ 
    console.log('response:', response); 
    } 

}); 

Если вы хотите узнать больше о Future библиотека Я рекомендую смотреть screencast


Обновление на 26/12/2017

Я просто хотел обновить этот ответ, как вы можете достичь того же, используя обещание и так, избавиться от «волоконных» зависимостей :)

Пример стоит тысячи и слова

import scrap from 'scrap'; 

Meteor.methods({ 
    'hof.add'(el) { 
     check(el, { 
      _link: String 
     }); 

     const promise = getHofInfo(el._link) 
      .then((inserter) => { 
       inserter.owner = Meteor.userId(); 
       Hof.insert(inserter); 
       return true; 
      }) 
      .catch((e) => { 
       throw new Meteor.Error('500', e.message); 
      }); 
     return promise.await(); 
    } 
}); 


function getHofInfo(_link) { 
    return new Promise((resolve, reject) => { 
     scrap(_link, function (err, $) { 
      if (err) { 
       reject(err); 
      } else { 
       const attakers = $('#report-attackers').find('li').text(); 
       const defender = $('#report-defenders').find('li').text(); 
       const _name = attakers + ' vs ' + defender; 
       const _date = new Date(); 
       resolve({ _name, _date, _link }); 
      } 
     }); 
    }); 
} 
+0

Я также сталкиваюсь с этой проблемой. Но я не хочу использовать модуль npm. Есть ли какой-либо пакет метеоров для этого, например, будущего волокна –

+0

@MariyaJames проверяет новое редактирование, вы можете сделать это без модуля – Rolljee

0

one better solution

с использованием волоконно-пакет

var Fiber = Npm.require('fibers'); 
... 
Meteor.methods({ 
    callAsync: function (args) { 
     var fiber = Fiber.current; 

     async(function (args) { 
      ... 
      fiber.run(res); 
     }); 

     return Fiber.yield(); 
    } 
}); 
1

Для любого нового метеорной видящего этот вопрос и интересно почему библиотека как будущее или волокна необходимо, это потому, что этот призыв до amazon.execute является асинхронным.

В Javascript многие операции, которые занимают длительный период времени, не запускают одну строку после следующего; Примеры, например, запись в базу данных, с использованием window.setTimeout или создание запросов HTTP. С такими методами, как исторически, вам нужно было обернуть код, который вы хотите запустить после факта в обратном вызове .

Будущее и волокна обеспечивают синтаксический сахар и дополнительные функциональные возможности, но их основная функциональность одинакова.

Meteor использует специальные закулисный приемы, чтобы сделать определенные встроенные операции (например, доступ к MongoDB) появляются синхронно, в то же время, пользуясь увеличенной производительности асинхронного кода. По этой причине вам обычно приходится беспокоиться о async при использовании внешних пакетов (например, Amazon в этом примере).


Here «са полностью конкретизирован выход пример использования как будущего и волоконных

Есть некоторые большие статьи, объясняющая природу синхронных/асинхронных в Метеоре на the Discover Meteor blog и в the Meteor Chef

1

Метеоре методы асинхронны, вы можете получить результат многими способами.

Использование модулей модуля npm (другой ответ объясняет это очень четко).

Есть другим способ без использования модуля NPM:

Via Session переменный:

Meteor.call('myMethod',args, function(error, result) { 
    if (error) { Session.set('result', error) } // Note that the error is returned synchronously 
    else { 
    Session.set('result', result) // Using : Session.get('result') will return you the result of the meteor call ! 
    } 
}); 

или через переменный шаблон:

Template.hello.onCreated(function helloOnCreated() { 
    // counter starts at 0 
    this.message = new ReactiveVar(0); 
}); 

Template.hello.helpers({ 
    message() { 
    return Template.instance().message.get(); 
    }, 
}); 

Template.hello.events({ 
    'click button'(event, instance) { 
    Meteor.call('myMethod', args, function (error, result) { 
     if (error) { Template.instance().message.set(error); } 
     else { 
     Template.instance().message.set(result); 
     } 
    }) 
    }, 
}); 

Надеется, что это поможет!

Смежные вопросы