To achieve your goal you need to use the Future .
How to use the future with Meteor 0.6?
Meteor.startup(function () { Future = Npm.require('fibers/future');
Your method is rewritten using Future:
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(); } });
Now it should work.
Meteor.call('search', 'harry potter', function(error, response) { if(error){ console.log('ERROR :', error); }else{ console.log('response:', response); } });
If you want to know more about the Future library, I recommend watching screencast
Update from 12/26/2017
I just wanted to update this answer, since you can achieve the same using the promise, and thus get rid of the βfiberβ dependencies :)
An example is worth a thousand words
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 }); } }); }); }