Scope of variables within $ .getJSON

4

The variable role gets a new value in every Loop , when it is inside $.getJSON it takes the second value of the array and does not change anymore. There are two console.log(); in the code, I put their return next to it. Does anyone know the cause of this and how to get rid of this undesirable scenario?

$(document).ready(function() {
  var emails = ["[email protected]", "[email protected]"],
    TeamRole = ["founder", "manager"],
    hashMail;

  for (var i=0 ; i < emails.length ; i++){ 
    hashMail = "http://www.gravatar.com/" + md5(emails[i].toLowerCase().trim()) + ".json?callback=?";
    role = TeamRole[i];
    console.log(role); // > founder > manager

    $.getJSON(hashMail, function (data) {
      console.log(role); // > manager > manager
      $("#profile-container").append(
            "<div>" +
                "<img src='" + data.entry[0].thumbnailUrl + "?s=200>" +
                "<p>" + data.entry[0].displayName + "</p>" +
                "<p>" + self.role + "</p>" +
                "<p>" + data.entry[0].aboutMe + "</p>" +
            "</div>";
      );
    });
  };
});
    
asked by anonymous 13.03.2014 / 19:00

1 answer

5

The problem is that getJSON is asynchronous. When callback executes, the loop is already finished. The scope of your variables is the function that contains them (in this case, the callback of document.ready), not the loop block. One solution is to introduce a new function, executed immediately, capturing each value of the role variable separately:

for (var i=0 ; i < emails.length ; i++){ 
  hashMail = "http://www.gravatar.com/" + md5(emails[i].toLowerCase().trim()) + ".json?callback=?";
  var role = TeamRole[i];
  console.log(role); // > founder > manager
  (function(role) {
      $.getJSON(hashMail, function (data) {
        console.log(role); // > manager > manager
        $("#profile-container").append(
              "<div>" +
                  "<img src='" + data.entry[0].thumbnailUrl + "?s=200>" +
                  "<p>" + data.entry[0].displayName + "</p>" +
                  "<p>" + role + "</p>" +
                  "<p>" + data.entry[0].aboutMe + "</p>" +
              "</div>";
        );
      });
  }(role));
};

Note: I added var to declare your role variable because it was turning global.

    
13.03.2014 / 19:04