0

Javascript noob here. Apologies if there are a ton of duplicate questions out there because it seems like this must be a fundamental js function thing, but I honestly can't find an answer to this. I'm trying to wrap an API GET call in a function, and I'm running into behavior that I don't understand. The code in question:

I'm using the node-rest-client package to call the mapquest geocoding API. I'm interested in the lat/long data only.
var Client = require('node-rest-client').Client;

If I make the GET call like this, I can access parsed as an object, which is what I want.

var address = 'New York'
var client = new Client();
var parsed;
client.get("http://www.mapquestapi.com/geocoding/v1/address?" +
                'key=' + mapquestKeys.consumer_key +
                '&location=' + address,
            function(data, response) {
              parsed = data.results[0].locations[0].latLng
              }
            );

// parsed == {lat, long}

But if I wrap this in a function:

function geocode(address){
  var client = new Client();
  var parsed;
  client.get("http://www.mapquestapi.com/geocoding/v1/address?" +
                  'key=' + mapquestKeys.consumer_key +
                  '&location=' + address,
              function(data, response) {
                parsed = data.results[0].locations[0].latLng
                }
              );
    return parsed
}

var address = 'New York'
parsed = geocode(address);

// parsed === undefined

parsed doesn't seem to be affected by the inner function; it's undefined. How can I return parsed as an object containing the data I want as in the first example? What the heck is going on here?

  • you need to wrap this into a promise, or return the result with callback. Callback would be like this: ``` function call(arg, callback) { client.get("http:////" + arg, function (data, response) { callback(data.results[0].locations[0].latLng) }) call("yolo", function (parsed) { console.log(parsed) }) } ``` promise is well described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise – Dmitrijs Balcers May 18 '18 at 17:41
  • Why oh why do so many people start using things like Ajax but refuse to read anything about before trying to use it? The "A" is for asynchronous. – gforce301 May 18 '18 at 17:41
  • missed var for parsed variable outside function – Akhil Aravind May 18 '18 at 17:44

3 Answers3

0

You never defined parsed in scope (externally to the function):

function geocode(address){
  var client = new Client();
  var parsed;
  client.get("http://www.mapquestapi.com/geocoding/v1/address?" +
                  'key=' + mapquestKeys.consumer_key +
                  '&location=' + address,
              function(data, response) {
                parsed = data.results[0].locations[0].latLng
                }
              );
    return parsed
}

var address = 'New York'
var parsed = geocode(address);

Notice the var parsed = geocode(address);

Robert Talada
  • 317
  • 1
  • 10
0

you need to wrap this into a promise, or return the result with callback. Callback would be like this:

function call(arg, callback) {
 client.get("http:////" + arg, function (data, response) { 
  callback(data.results[0].locations[0].latLng)
 });
}

call("yolo", function (parsed) { console.log(parsed) })

promise is well described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Dmitrijs Balcers
  • 157
  • 1
  • 12
0

In:

function geocode(address){
  var client = new Client();
  var parsed;
  client.get("http://www.mapquestapi.com/geocoding/v1/address?" +
                  'key=' + mapquestKeys.consumer_key +
                  '&location=' + address,
              function(data, response) {
                parsed = data.results[0].locations[0].latLng
                }
              );
    return parsed
}

var address = 'New York'
parsed = geocode(address);

// parsed === undefined

You never defined parsed outside of the scope of your function. Also you're returning parsed inside of the function before it's had a chance to retrieve from the GET request. If you wanted to do it this way, you'd need to put return(prased) inside the callback function of client.get. A better way to do it is to wrap it inside a Promise like so:

function geocode(address){
    return new Promise((resolve, reject) => {
        var client = new Client();
        client.get("http://www.mapquestapi.com/geocoding/v1/address?" +
                'key=' + mapquestKeys.consumer_key +
                '&location=' + address,
                function(data, response) {
                if(data){
                    resolve(data.results[0].locations[0].latLng)
                }
                else{
                    reject(response)
                }
                  });
    })
  };


var address = 'New York';
var parsed;
geocode(address).then(function(latlong){
    parsed = latlong
}).catch(err => {
    console.log(err)});

Here, parsed will only evaluate to latlong once the Promise has been resolved (the GET request has returned successful). It will also reject the Promise if data of the GET request is NULL and return an error.

If you wanted to then do something with parsed you could include that in the .then() statement.

Learning how to code in Javascript means learning how to write code asynchronously. Promises help you treat things which are by default asynchronous as synchronous.

jmkmay
  • 1,441
  • 11
  • 21