Scope of variables within $.getJSON

Asked

Viewed 483 times

4

The variable role receives a new value in each Loop, when she’s inside the $.getJSON it takes the second value of the array and changes no more. There are two console.log(); in the code, I put their return next to it. Someone knows 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>";
      );
    });
  };
});

1 answer

5


The problem is that getJSON is asynchronous. When the callback executes, the loop has already ended. The scope of its variables is the function that contains them (in this case, the callback Document.ready), not the loop. One solution is to introduce a new function, executed immediately, capturing each variable value role 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: added var to declare your variable role, because she was going global.

  • It worked, but it has more of a "strange" behavior. The email array, let’s suppose it contains "[email protected]" and "[email protected]". Although the function is APPEND the code inserts backwards.

  • 2

    It "appenda" in the order in which the answers arrive. There is no guarantee of order for receiving the answers of asynchronous requests. The answer that arrives first is inserted first, and is instead in the list.

  • @Phellipelins If you cannot resolve this issue of the append order, I suggest posting a separate question, as it is a totally different problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.