2

Iam having some problems with a function I wrote. I want to wrap this whole thing into a function called myClosestCity that returns the name of the city based on a JSON feed that gives coordinates from users IP. As far as I can see the problem is within the getJSON function. I've tried with global variables, getters and setters (which didnt work at all) and just about everything I could think of Googling.

By the way, for the code to run you'll need to include a script from Google Maps: http://maps.google.com/maps/api/js?sensor=false&libraries=geometry

Anyway, here's my whole code:

var stavanger = new google.maps.LatLng(58.96998, 5.73311);
var oslo = new google.maps.LatLng(59.91387, 10.75225);
var trondheim = new google.maps.LatLng(63.43051, 10.39505);
var bergen = new google.maps.LatLng(60.39126, 5.32205);

function calcDistance(p1, p2){
  return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}



$.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function(data) {
myLocation = new google.maps.LatLng(data.geoplugin_latitude,data.geoplugin_longitude);
var distances = new Array();
distances[0] = calcDistance(myLocation, stavanger);
distances[1] = calcDistance(myLocation, oslo);
distances[2] = calcDistance(myLocation, trondheim);
distances[3] = calcDistance(myLocation, bergen);



maxValue = Math.min.apply(this, distances);
var findThisIndex = maxValue + "";
var placeNo = $.inArray(findThisIndex, distances);


if(placeNo == 0) {
    closestCity = "Stavanger";
}

else if (placeNo == 1){
    closestCity = "Oslo";
}

else if(placeNo == 2) {
    closestCity = "Trondheim";
}

else if(placeNo == 3){
    closestCity = "Bergen";
}

else {
    closestCity = "Ukjent"; // Unknown in Norwegian
}

alert(closestCity);
  });

Update: It's the closestCity variable I'd like to return!

  • It's a little confusing what exactly you're asking... are you trying to make the asynchronous getJSON behave like a synchronous function? (One that blocks the calling function until it can return its result.) – jonvuri Dec 16 '12 at 17:27
  • Thanks for your fast reply. Iam not really sure how I want to do it, but I want to wrap all the code into a function and return the closestCity variable. I see now that it might be possible to move a lot of the code out of the getJSON function. I'll give that a try, and post a reply if it does the trick. A little confused with my own messy code here. – Steffen Martinsen Dec 16 '12 at 17:33
  • right off the bat ..based on title alone you are following a common mistake path with AJAX. Consume the AJAX data in success callback of the request. Without getting into deffered objects,AJAX is asynschronous by definition so you can't wrap a function around it and return data – charlietfl Dec 16 '12 at 17:36
  • It is working well. do you just want to structure the code? – closure Dec 16 '12 at 17:37

4 Answers4

3

A bit late, but here's how I would do it, by returning a promise :

function myClosestCity() {
    var def = $.Deferred();
    $.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function(data) {
        var myLocation = new google.maps.LatLng(data.geoplugin_latitude, data.geoplugin_longitude),
            distances = [calcDistance(myLocation, places.stavanger),
                         calcDistance(myLocation, places.oslo),
                         calcDistance(myLocation, places.trondheim),
                         calcDistance(myLocation, places.bergen)
                                            ],
            minValue = distances.indexOf(Math.min.apply(Math, distances).toString());
        def.resolve(Object.keys(places)[minValue]);
    });
    return def.promise();
}

And you use that like so:

myClosestCity().done(function(city) {
    console.log(city); // returns the closest city
});

And here's a DEMONSTRATION

adeneo
  • 312,895
  • 29
  • 395
  • 388
2

If I understand you want to do something like the following:

var myClosestCity = function(fn){
    $.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function(data){
       /* calculate closestCity */
       ...
       /* pass closestCity to the callback */
       fn(closestCity);
    });
};​

Since $.fn.getJSON is an asynchronous function you can pass a callback function (fn) which will be called after the response from the server and the calculation of closestCity is done.

You can use it the following way passing a callback function.

myClosestCity(function(closestCity){
  alert(closestCity);
});
Alexander
  • 23,432
  • 11
  • 63
  • 73
1

You can define your function and then wait for server response, then use your closestCity. You cand modify your code in this way:

var myClosestCity = function(callback) {
    var stavanger = new google.maps.LatLng(58.96998, 5.73311);
    var oslo = new google.maps.LatLng(59.91387, 10.75225);
    var trondheim = new google.maps.LatLng(63.43051, 10.39505);
    var bergen = new google.maps.LatLng(60.39126, 5.32205);

    function calcDistance(p1, p2) {
        return (google.maps.geometry.spherical.computeDistanceBetween(p1,      p2) / 1000).toFixed(2);
    }


    $.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function(data) {
        myLocation = new google.maps.LatLng(data.geoplugin_latitude, data.geoplugin_longitude);
        var distances = [];
        distances[0] = calcDistance(myLocation, stavanger);
        distances[1] = calcDistance(myLocation, oslo);
        distances[2] = calcDistance(myLocation, trondheim);
        distances[3] = calcDistance(myLocation, bergen);



        maxValue = Math.min.apply(this, distances);
        var findThisIndex = maxValue + "";
        var placeNo = $.inArray(findThisIndex, distances);


        if (placeNo === 0) {
            closestCity = "Stavanger";
        }

        else if (placeNo == 1) {
            closestCity = "Oslo";
        }

        else if (placeNo == 2) {
            closestCity = "Trondheim";
        }

        else if (placeNo == 3) {
            closestCity = "Bergen";
        }

        else {
            closestCity = "Ukjent";
        }

        if (typeof callback === "function") {
            callback.call(null, closestCity);
        }
    });
};


//call the function and display the closestCity on callback
myClosestCity(function(closestCity) {
    alert(closestCity);
});?
joeyramone76
  • 241
  • 1
  • 4
0

Here is the implementation of the function wrapped in html

    <!DOCTYPE html>
    <html>
    <head>
    <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    <script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"></script>
    <meta charset=utf-8 />
    <title>Test</title>
    </head>
    <body>

      <script>
        function myClosestCity(closestCity) {
          alert(closestCity);
        }

        function findClosestCity(fnCallback) {
          var stavanger = new google.maps.LatLng(58.96998, 5.73311);
          var oslo = new google.maps.LatLng(59.91387, 10.75225);
          var trondheim = new google.maps.LatLng(63.43051, 10.39505);
          var bergen = new google.maps.LatLng(60.39126, 5.32205);

          function calcDistance(p1, p2) {
            return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
          }


          $.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function(data) {
            myLocation = new google.maps.LatLng(data.geoplugin_latitude, data.geoplugin_longitude);
            var distances = new Array();
            distances[0] = calcDistance(myLocation, stavanger);
            distances[1] = calcDistance(myLocation, oslo);
            distances[2] = calcDistance(myLocation, trondheim);
            distances[3] = calcDistance(myLocation, bergen);

            maxValue = Math.min.apply(this, distances);
            var findThisIndex = maxValue + "";
            var placeNo = $.inArray(findThisIndex, distances);

            if (placeNo == 0) {
              closestCity = "Stavanger";
            } else if (placeNo == 1) {
              closestCity = "Oslo";
            } else if (placeNo == 2) {
              closestCity = "Trondheim";
            } else if (placeNo == 3) {
              closestCity = "Bergen";
            } else {
              closestCity = "Ukjent";
              // Unknown in Norwegian
            }

            fnCallback(closestCity);
          });
        }

        // When everything loads call the getJSON with handle of my function myClosestCity
        // 

        window.onload = function() {
          findClosestCity(myClosestCity);
        };
      </script>


    </body>
    </html>

Demo here

closure
  • 7,412
  • 1
  • 23
  • 23