0

I am fetching some data from PHP, the code all works fine and the result of my PHP is a json list sorted by Likes.

getJson result:

[{"ref":"2038", "name":"aaa", "likes":"10"}, 
{"ref":"2032", "name":"sss", "likes":"9"},
{"ref":"1875", "name":"off", "likes":"6"},
{"ref":"0087", "name":"mki", "likes":"3"},
{"ref":"1256", "name":"qvb", "likes":"3"},
{"ref":"8754", "name":"dsa", "likes":"2"},
{"ref":"4359", "name":"ety", "likes":"0"},
...]

My problem is that when I loop trough the results, a geolocation function is called to calculate the distance of each member. It seems that the geolocation function is not called at the same time and the list becomes mixed up.

My question is : how can I wait for the geolocation function to calculate the distance, append the result on the list and continuing to the next element? I was looking into using promise but I am not sure how to use it with my code.

jQuery:

    function loadAllMembersData() {

        var url_featured = "https://example.com/BBB?members=all";

        $.getJSON(url_featured, function (result) {
             //10 results
            $.each(result, function (i, field) {
                var ref = field.ref;
                var name = field.name;
                var likes = field.likes;
                var lat = field.lat;
                var lng = field.lng;

console.log(i); //index(i) is fine 0 to 9



                getLocationServices(lat, lng, function (r) {

console.log(i); //index(i) becomes mixed up (2, 3, 0, 6,...) 

                    var displayDistance = r + " miles away";

                    $("#membersList ul").append('<li>' +
                            '<a href="#" class="item-link item-content" style="padding: 0">' +
                            '<div>' + displayDistance + '</div>' +
                            '<div>' + name + '</div>' +
                            '<div>' + likes + '</div>' +
                            '</a>' +
                            '</li>');

                });




            });
        });
    }
SNos
  • 3,430
  • 5
  • 42
  • 92
  • 1
    Don't wait for the geolocation call to end; that will just waste time. Instead make the calls as you are then display all content at once. You can `sort()` it as well if needed. – Rory McCrossan Sep 28 '16 at 13:08
  • my call is limited to 10 results at the time and when scrolling down it loads more result. It will be hard to sort the list – SNos Sep 28 '16 at 13:21

1 Answers1

-1

I think that your vars i, name and likes behaving strange in the inner getLocationServices callback is the normal behaviour. They are outer scopes variables being defined in the $.each callback -which is outer scope to the getLocationServices callback-, but then, when that callback access to them -some milliseconds later-, the $.each has already set them to new values in subsequent iterations. In fact, I find pretty strange your comment stating i is being mixed up, while I would expect to i to be always 9 inside the callback, and the name and likes vars to be the ones of the latest JSON element. Maybe you're touching that same vars later in your code, so when the callback access them they are somehow randomly mixed?

Well, if I understand your issue well, this should fix the problem:

function loadAllMembersData() {

    var url_featured = "https://example.com/BBB?members=all";

    $.getJSON(url_featured, function (result) {
         //10 results
        $.each(result, function (i, field) {
            var ref = field.ref;
            var name = field.name;
            var likes = field.likes;
            var lat = field.lat;
            var lng = field.lng;

            console.log(i); //index(i) is fine 0 to 9


        (function( theName , theLikes ){
            getLocationServices(lat, lng, function (r) {

              console.log(i); //This will be fucked up. It's the standard behaviour
              console.log(theName); //But now, this value should be correctly fixed to its outer scope counterpart. 

                var displayDistance = r + " miles away";

                $("#membersList ul").append('<li>' +
                        '<a href="#" class="item-link item-content" style="padding: 0">' +
                        '<div>' + displayDistance + '</div>' +
                        '<div>' + theName + '</div>' +
                        '<div>' + theLikes + '</div>' +
                        '</a>' +
                        '</li>');

            });
        })(name , likes);
        });
    });
}

In every .each iteration, you pass the values of that item as parameters to an IIFE, so you don't rely on the value of outer scope vars name and likes.

Sergeon
  • 6,638
  • 2
  • 23
  • 43