jquery deferred in for loop

笑着哭i 提交于 2019-12-24 07:03:46

问题


So I have been working on jquery deferred but am having trouble when retrieving data in a loop. The deferred portion seems to only process the data from the final iteration. If there is only one item in the array, it fails as well, so I am not sure what is going on.

I have various city names, and I am trying to get central coordinates for each city from the google maps reverse geocoded

Here is my function that gets the central coordinates:

function getGroupLatLng(groupname){
    var deferred = new $.Deferred();

     geocoder.geocode( { 'address': groupname}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
              deferred.resolve(results);

          alert(results[0].geometry.location.lat());
      } else {

      }

    });
    return deferred.promise();
}

This is where the function is called, and a div is appended once the result is returned:

var newGroupsLength = newGroups.length;

for (i = 0; i < newGroupsLength; i++) {

    newGroups[i]['counter']=counter;
    var locationName = newGroups[i]['name'];
    counter++;
    alert(locationName);
    $.when(getGroupLatLng(locationName)).then(function(results){
        alert("lat = "+results[0].geometry.location.lat());
        var lat=results[0].geometry.location.lat();
        var lng=results[0].geometry.location.lng();
        console.log(newGroups[i]); //this is running the proper number of times, but it logs the results from the final looped item, 'n' number of times. 

        newGroups[i]['lat']=lat;
        newGroups[i]['lng']=lng;

        var jsonArray=[];
        jsonArray = newGroups[i];
        var template = $('#groupsTemplate').html();
        var html = Mustache.to_html(template, jsonArray);
        $('#groups-container').append(html);
    });
}

The problem I am having is that the deferred loop seems to process the last item in the for loop 'n' number of times, with 'n' being the number of items in the newGroupsLength array. Of course it should process each item one time. If the deferred action is removed, it all works fine.

Sincere thanks for any help. It is greatly appreciated


回答1:


There is two facts that cooperate to give that result:

  1. When writing an object to the log, it's the reference to the object that is written, not a copy of the data. If the object changes after being logged, the log will show the changed data.

  2. The loop will already have completed before the callback function for then is called the first time. That means that i will have the same value for all callbacks, so you put all results in the same object.

So, the values in newGroups[i] will change for each response that is handled, but you will only see the last values in the log because that's what the object contains by the time the log shows it.

To make each iteration in the loop keep the value of i for later when the response arrives, you can use an IIFE (immediately-invoked function expression) to create a local variable for each iteration:

var newGroupsLength = newGroups.length;

for (i = 0; i < newGroupsLength; i++) {

  (function(i){

    newGroups[i]['counter']=counter;
    var locationName = newGroups[i]['name'];
    counter++;
    alert(locationName);
    $.when(getGroupLatLng(locationName)).then(function(results){
        alert("lat = "+results[0].geometry.location.lat());
        var lat=results[0].geometry.location.lat();
        var lng=results[0].geometry.location.lng();

        newGroups[i]['lat']=lat;
        newGroups[i]['lng']=lng;

        console.log(newGroups[i]); // log the object after setting the values

        var jsonArray=[];
        jsonArray = newGroups[i];
        var template = $('#groupsTemplate').html();
        var html = Mustache.to_html(template, jsonArray);
        $('#groups-container').append(html);
    });

  })(i);

}


来源:https://stackoverflow.com/questions/28552302/jquery-deferred-in-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!