node.jsmeteormeteor-methods

Meteor : Retrieve value in Meteor.call which calls a server method having promise


I have an internally maintained npm package myNpmPackage which exports a function (for e.g. fnTestMicroSerConn ) as below:

const rp = require('request-promise-native')

exports.fnTestMicroSerConn = function () {
  return new Promise(function(resolve, reject) {
    var options = {
      method: 'GET',
      uri : "http://example.net", 
      resolveWithFullResponse: true,
    }
    rp(options)
      .then(function (response) {
        if (response.statusCode !== 200){
          console.error("http not 200 but : ",response.statusCode)
          resolve(false)
        } else  {
          console.info("connected successfully : "+response.body)
          resolve(response)
        }
      })
      .catch(function (err) {
          console.error("Error in establishing connectivity  : ",err)
          resolve(false)
      })
    })
}

I then need to call the above exported function from a Meteor method like so:

import { Meteor } from 'meteor/meteor';
import myNpmPackage from 'myNpmPackage';

Meteor.methods({   
 foo: function () {
   myNpmPackage.fnTestMicroSerConn().then(function (response){
     console.log(" My response: ",response.body);
    return(response.body)
   })
 }
});

console.log(" My response: ",response.body); gets executed successfully and I can see the expected value in the server console log. So till here it's good.

However, now I want to pass the value of response.body to the client side. In short, when I do below on the client :

Meteor.call("foo", function (err, response) {
      console.log("calling foo");
      if(!err){
        console.log("response : ",response);
      } else {
        console.log("err : ",err);
      }
    })

Unfortunately, currently I am getting undefined on the client for console.log("response : ",response);

Note: I am using the Meteor Promise package from here

Let me know if any more details are needed or any thing is unclear. I am very new to the Promise style of coding, hence, this can sound as a noob question.


Solution

  • Meteor methods called from clients by Meteor.call run synchronously to prevent clients from pending, even if a callback is supplied.

    Your foo method does not wait for that promise inside. It runs past fnTestMicroSerConn() call without hesitation and ends up with no more statement to execute, returning undefined as a result. By the time the promise resolved and logged the expected message on the server console, the method had been exited.

    To get resolved/rejected result of that promise, you can return the promise from the method to the caller, and the client would be able to respond to the promise.

    Meteor.methods({   
     foo: function () {
       return myNpmPackage.fnTestMicroSerConn();
     }
    });
    
    Meteor.call("foo")
      .then( response => console.log("My response: ", response.body) )
      .catch( err => console.log("err : ",err) );
    

    Meteor methods is powerful. The API documentation of methods contains much information and is worth mastery.