Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

javascript - Returning value from callback within Meteor.method

I am running into something I don't understand with Meteor. I have this method, which takes a query, sends it to amazon, and then in the callback of that function I try to return the results.

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

But when I put the following into the console in my browser (chrome):

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

I get the this:

undefined
response: undefined          VM13464:3

I think I understand that the first undefined comes from the method not returning anything on the client, but the callback doesn't seem to work at all.

The amazon.execute(...) is definitely returning something, as the console.log right above the return does log the info I'm looking for.

Any ideas what's going wrong and how I can fix it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to use Future to achieve your goal.

How to use future since Meteor 0.6?

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

 // use Future here
}

Your method rewritten with 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 learn more about Future library I recommend watching screencast


Update on 26/12/2017

I just wanted to update this answer as you can achieve the same thing using promise and so, get rid of the "fibers" depedencies :)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...