1

I can't seem to get my head around this problem.

I'm using the Maxmind GeoIP2 JavaScript API with an async callback to return latitude, longitude and subdivision or region.

    <script type="text/javascript" src="//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js"></script>
    <!--Html tags ... -->
    <script type="text/javascript">
        geoip2.city(
            function (response) {
                var latitude = "";
                var longitude = "";
                var region = "";

                latitude = response.location.latitude;
                longitude = response.location.longitude;
                region = response.subdivisions[0].iso_code;

                //Other operations.                       
            },
            function (error) {
                try {
                    console.log(error);
                }
                catch (ex) {
                    alert(ex);
                }
            }
        );
    </script>
    <!--Html tags ... -->
    <script type="text/javascript">
        $(document).ready(function () {
            //Synchronous JavaScript against the DOM.
        });
    </script>

Those values should then come back and are written to the DOM in an ASP.NET Web Forms Update Panel which does an auto postback to the server. The server then does a lookup in a custom database and returns the nearest 50 or so locations as points to a Google Map which is rendered on postback by passing jQuery document ready an anon function.

Of course, this isn't what happens. Everything does not occur sequentially. (I wouldn't expect it to, I just need to know the correct way to address the issue.)

I'd like to add a couple of other things:

  1. It worked prior to Maxmind changing from the old synchronous
    JavaScript API calls to this async callback API.
  2. This is not my code or approach. I've inherited this beauty.
0

1 Answer 1

0

You just need to nest your synchronous stuff inside any async callback. The key to async programming is remembering that functions in JS are just objects and can be passed around.

So you define all your callbacks upfront, then chain them into one another. The below is by way of example (I assumed your database lookup was synchronous) so apologies if doesn't make perfect sense, but gives an idea on how to do the async bit.

Put everything inside the $(document.ready) rather than splitting it up into 2 scripts:

$(document).ready(function () {

    var weHaveFailed = function(){
        // do sad things
    };

    var getLocation = function(successCallback, failureCallback){
      geoip2.city(
        function (response) {
          // success!! Unpack the response
          var latitude = response.location.latitude;
          var longitude = response.location.longitude;
          var region = response.subdivisions[0].iso_code;

          // ... do other stuff
          // then callback the passed in successCallback function with your coordinates
          // and the function we want to execute when THAT is successful
          successCallback(latitude, longitude, region, updateTheLocations);                   
        },
        function (error) {
          // failure :(
          console.log(error.message);
          failureCallback();
        }
      );

    var lookup = function(lat, long, reg, successCallback){
      var locations = [];
      // ...get the data from the database, is this sync?
      // ...assign the response to our locations array
      // ... and call the passed in successCallback with the locations array
      successCallback(locations);
    };

    var updateTheLocations = function(locations){
      // We pass in the locations from the lookup call
      // do happy things, like synchronous JavaScript against the DOM
    };

    // start the ball rolling, passing in the function we want to run when geoip2 gets the data
    getLocation(lookup, weHaveFailed);

});
Sign up to request clarification or add additional context in comments.

3 Comments

This, I believe, is the right approach to the problem. To answer your question, I did not implement it though. I have for the time being reverted (time constraints) to the Maxmind GeoIP API legacy calls for latitude, longitude and region. But your input was appreciated.
More information for other users who would like to use the old sync Maxmind GeoIP Legacy JavaScript API instead of callbacks: dev.maxmind.com/geoip/legacy/javascript. Using the city API and the geoip_region(), geoip_latitude(), geoip_longitude() functions. I would recommend using callbacks and the approach by @drjimmie1976 though if you have time to implement.
@user888298 If only we had time to (re-)code everything like we wanted to! ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.