WonderSteve
WonderSteve

Reputation: 927

Returning data from server method to client after server calls an HTTP API

I am trying to learn Meteor, starting by writing a simple application where the server calls an HTTP API based on user input, processes the information, then returns it to the client to display it.

I am not having much success. I can't seem to return the result from server to client:

if (Meteor.isServer) {
  Meteor.methods({
    checkTransit: function(method, url, options) {
      this.unblock();
      return Meteor.http.call(method, url, function(error, result) {
        if (error) {
          console.log('SERVER ERRR');
          console.log(error);
        } else {
          console.log('SERVER RESULT');
          console.log(result);
        }
      });
    }
  })
}

if (Meteor.isClient) {

   Template.body.events({
    "submit .new-task": function(event) {
     // Prevent default browser form submit
     event.preventDefault();

     var text = event.target.text.value;

     var method = 'GET';
     var url = 'http://sometransitapi.com';
     var options = {
       headers: {
         'accept': 'application/XML',
         'content-type': 'application/XML'
       }
     }

     Meteor.call('checkTransit', method, url, options, function (error, result) {

       if (error) {
          console.log('CLIENT ERRR');
          console.log(error);
        } else {
          console.log('CLIENT RESULT');

          var parser;
          parser = new DOMParser();
          var xmlDoc
          xmlDoc = parser.parseFromString(result, "text/xml");

          console.log(xmlDoc);
        }
     })

   }
 })
}

I can see the results being returned to the result variable at isServer, but I can not pass the result to the xmlDoc variable in isClient. What am I doing wrong? Is this the correct way to structure things for what I want to do in Meteor?

Upvotes: 1

Views: 1760

Answers (2)

Kassym Dorsel
Kassym Dorsel

Reputation: 4843

If you want to keep the logic on the server side then @Curtis' answer should help you.

Looking at what you have, I don't see much of a point of getting the server to do the work. The Http api is available everywhere in Meteor. You are just fetching data, which can be solely done on the front end. This would also technically make it faster. Taking your code and moving it around a bit you get the following.

if (Meteor.isClient) {
 Template.body.events({
   "submit .new-task": function(event) {
     // Prevent default browser form submit
     event.preventDefault();

     var text = event.target.text.value;

     var method = 'GET';
     var url = 'http://sometransitapi.com';
     var options = {
       headers: {
         'accept': 'application/XML',
         'content-type': 'application/XML'
       }
     }
     Http.call(method, url, options, function (error, result) {
       if (error) {
          console.log('CLIENT ERRR');
          console.log(error);
        } else {
          console.log('CLIENT RESULT');

          var parser;
          parser = new DOMParser();
          var xmlDoc
          xmlDoc = parser.parseFromString(result, "text/xml");

          console.log(xmlDoc);
        }
     });
    }
 });
}

Upvotes: 1

Curtis
Curtis

Reputation: 681

Meteor.http.call is being called asynchronously in your server code (you are passing a callback). The functions in your Meteor.methods object expect to return a value, so you should be calling Meteor.http.call synchronously. Changing your server code to below should do the trick.

if (Meteor.isServer) {
  Meteor.methods({
    checkTransit: function(method, url, options) {
      this.unblock();
      // This will throw an exception and return it as the error object
      // in your Meteor.call if an error occurs, otherwise it will
      // return an empty error object and the result object will be
      // the return value from Meteor.http.call
      return Meteor.http.call(method, url);
    }
  })
}

Upvotes: 4

Related Questions