1

Ok so i am using a method to make a request and pull some tables from another URL

Meteor.methods({
    gimmetitle: function () {

        var url = 'http://wiki.warthunder.com/index.php?title=B-17G_Flying_Fortress';

        request(url, function(err, response, body) {
            $ = cheerio.load(body);
            var text = $('.flight-parameters td').text();
            console.log(text);

            return text;
        });          
    }
});

When called the td's in the table succesfully print to the server console: http://prntscr.com/721pjh

Buuut, when that text is returned from that method to this client code, undefined is printed to the console:

Template.title.events({
    'click #thebutton': function () {
         Meteor.call('gimmetitle',  function(error, result){
            Session.set('gogle', result);
        });

         var avar = Session.get('gogle');
         console.log(avar);
    }
});

Ideas?

Orbit
  • 2,985
  • 9
  • 49
  • 106
  • I suggest you post your code directly within code tags, so that it's easier to use/fiddle with instead of just posting a screenshot. – Rushy Panchal May 06 '15 at 02:42
  • @RushyPanchal added pastes. – Orbit May 06 '15 at 02:48
  • You should paste your code directly into the question, not link elsewhere. If someone wants to help, it's discouraging if they have to put more effort into going elsewhere. I did so now but I also recommend copying the output and pasting it instead of using an image. Just a tip :) – Rushy Panchal May 06 '15 at 02:52
  • @RushyPanchal ..you think that looks better? – Orbit May 06 '15 at 02:56
  • Not necessarily that it looks better, just that it's easier to use. For example, if I had a response or if I wanted to try finding a solution, I would have to copy your code. It's much easier if I can copy it directly instead of going to a link or typing it out from an image. – Rushy Panchal May 06 '15 at 02:58
  • There are several solutions to your core problem (using async functions inside a meteor method) here: http://stackoverflow.com/questions/12569712 . However, this question also implies that you have a misunderstanding of how asynchronous code works (that console.log must be inside Meteor.call) – slebetman May 06 '15 at 03:06
  • your problem is your return is not the return from your method call, its on a call back on a request..... the request fires off, and your method drops out the bottom having returned nothing. – Keith Nicholas May 06 '15 at 03:06
  • This question has been asked more than once on SO. Search for related answers. The bottom line is that something running in the future cannot return something which is available now. See http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call. –  May 07 '15 at 05:33
  • @torazaburo Revert my thread, this had nothing to do with Ajax. + More questions = more results for people with questions. + This was fixed anyway, see my answer: http://stackoverflow.com/a/30092595/3917064. – Orbit May 07 '15 at 06:03
  • async === ajax, same thing. More questions = more clutter and spam. –  May 07 '15 at 06:30
  • lol more questions on a site for questions = spam? Lol logic checks out. /s – Orbit May 07 '15 at 06:48

2 Answers2

1

You need to understand two different things here :

  • On the client side, making some calls to the server is always asynchronous, because we have to deal with network latency. That's why we use callbacks to fetch the result of Meteor methods : this code is executed some time in the future, not right away.

This is why Session.set('gogle', result); is actually executed AFTER var avar = Session.get('gogle'); even though it appears before in your event handler code flow.

  • Contrary to template helpers, event handlers are NOT reactive, so it means that when you set the Session variable to the result of the method, the event handler code is not automatically reexecuted with the new value of Session.get('gogle').

You'll need to either do something with the result right in the Meteor method callback, or use a reactive computation (template helpers or Tracker.autorun) depending on Session.get('gogle') to rerun whenever the reactive data source is modified, and use the new value fetched from the server and assigned to the Session variable.

saimeunt
  • 22,666
  • 2
  • 56
  • 61
  • Thanks. Heres a thought...instead of using the Sessions and instead just try to print the result via `console.log(result);` inside a `setTimeout` function after a few seconds, why would that not work? Obviously the call should complete by that time? – Orbit May 06 '15 at 03:55
  • It would be terrible design and introduce subtle bugs on some cases (high network latency, error from the server, etc...). Use the Meteor method callback to detect server response, never a timeout. – saimeunt May 06 '15 at 05:25
  • According to my definition of code correctness, it wouldn't work because it could potentially fail on not so uncommon edge cases. Using something not appropriate to perform a task when another thing designed specifically to accomplish this task exists is not a good idea. – saimeunt May 06 '15 at 06:49
0

Quick update..Was able to fix this with just 1 line of code lol.

instead of request(url, function(err, response, body) i used the froatsnook:request package and used var result = request.getSync(url, {encoding: null}); and then just replaced $ = cheerio.load(body); with $ = cheerio.load(result.body);.

Orbit
  • 2,985
  • 9
  • 49
  • 106