Method returns 'undefined' on server side


#1

Hi everyone

I’m retrieving a key from an API with a function on the server side. I want to call this function in a function and let it return the key. The problem is that it returns undefined.

With just the first function, the key is succesfully returned. The problem is when I want that function to return the value. I’m running this in my server folder.

Meteor.methods({
	'requestAccessToken': function(){
		HTTP.call( 'POST', 'url', {
		  data: {
		    'grant_type': '',
	      	'client_id': '',
	      	'client_secret': ''
		  }
		}, function( error, response ) {
		  if ( error ) {
		    console.log( error );
		  } else {
		    var jsonResult = JSON.parse(response.content);
		    console.log('Access token: ' + jsonResult['access_token']);
		    return jsonResult['access_token'];
		  }
		});
	},
	'createTournament': function(){
		var access_token = "";

		Meteor.call('requestAccessToken', '', function(error, result){
		    access_token = result;
		});
	}
});

The last Meteor.call returns undefined. Any ideas?

Thanks in advance!


#2

Try something along these lines… untested code but looks like it should be along the right lines.

Meteor.methods({
  async 'createTournament'() {
    try {
      const res = await requestAccessToken();
      return res;
    } catch (error) {
      throw new Meteor.Error(error);
    }
  }
});

function requestAccessToken () {
  return new Promise((resolve, reject) => {
    HTTP.call( 'POST', 'url', {
      data: {
        'grant_type': '',
        'client_id': '',
        'client_secret': ''
      }
    }, ( error, response ) => {
      if ( error ) reject(error);
      const jsonResult = JSON.parse(response.content);
      console.log('Access token: ' + jsonResult['access_token']);
      resolve(jsonResult['access_token']);
      }
    });
  });
}
  	

The reason it returns undefined is due to the context in which you’re calling it. So moving the logic into a normal function outside that context will work better. Also wrapping it into a promise so you can deal with the async callback.


#3

Here’s another way.

let Future = require('fibers/future');

Meteor.methods({
  'createTournament': function(){
     let future = new Future();
     Meteor.call('requestAccessToken', '', function(error, result){
        future.return(result);
     });
     let access_token = future.wait();
  }
});

#4

Hi, thank you for the suggestions. I’m not familiar with this yet though and I can’t seem to figure out how to run the ‘createTournament’ method now? I used Meteor.call before but now it says “Error invoking Method ‘createTournament’: [[object Object]]”.

Edit: all good, apparentely it was a variable that didn’t exist.

@Dan Thank you for the suggestion, definitely seems interesting and I will try your solution when I find the time.


#5

I think you can ditch the promise there and just make it an async function so it returns a promise automatically. async functions should wrap your function in a Promise, convert returns to resolve()s, and convert throws to reject()s

async function requestAccessToken () {
    HTTP.call( 'POST', 'url', {
      data: {
        'grant_type': '',
        'client_id': '',
        'client_secret': ''
      }
    }, ( error, response ) => {
      if ( error ) throw error;
      const jsonResult = JSON.parse(response.content);
      console.log('Access token: ' + jsonResult['access_token']);
      return jsonResult['access_token'];
      }
    });
}