0
$(".room").each(function () {
    i = i + 1;
    alert(i);
    roomid = $(this).attr("id");
    alert(roomid);

    $.get("QueryRoom.aspx?ID=" + roomid, function (data) {
        $("#" + roomid).html(data);
    });
});

});

It seems the roomid in the middle of my get query does not update and is stuck at #22 (the last room ID). The get request performs okay because I can see the div changing content.

Can anyone help?

5
  • by the time your first get request returns your loop is finished so the roomid variable represents the last datum Commented Jun 13, 2014 at 14:45
  • it is because you are redefining i each time you execute the function. (or better .. letting I be the default value since it's not defined on eah new run of the function). If you want I to remain between triggered events you need to track it outside the function and bring it into the function. Commented Jun 13, 2014 at 14:45
  • @olly_uk I had a feeling this was the case - how can I prevent this? Commented Jun 13, 2014 at 14:45
  • @Corbin you wrap it in a closure Commented Jun 13, 2014 at 14:46
  • @FeistyMango - Could you please show me how, I'm not sure I understand.. Commented Jun 13, 2014 at 14:48

2 Answers 2

3

What you need is a closure to preserve the value of roomid until the asynchronous call is finished. One way to create a closure is using an immediate function where you pass the value of roomid into it as a parameter.

There are a billion articles that explain closures in detail but simply put: a closure is any function that accesses a variable from an outer scope. A special object call a closure is created in this situation in order to preserve the memory locations of all the objects/variables that are referenced within the inner function, creating a context of sorts.

In my example, once you make this closure, you are effectively hiding roomid in the outer scope because you have an immediate function with a variable of the exact same name. So therefore, you will only be accessing the value within the immediate function and it will have the correct id when the ajax call completes.

$(".room").each(function () {
        i = i + 1;
        alert(i);
        roomid = $(this).attr("id");
        alert(roomid);
        (function(roomid) {
            $.get("QueryRoom.aspx?ID=" + roomid, function (data) {
                $("#" + roomid).html(data);
            });
        })(roomid);
    });
});
Sign up to request clarification or add additional context in comments.

Comments

1

roomid is shared between all of the callback functions to $.get. The loop executes quickly enough to increment it fully before any of the callbacks complete so they all get the largest value. You can correct this in various ways, but the simplest is to pass in roomid at its current value to a closure where the ajax call is made:

(function (roomid) {
    $.get("QueryRoom.aspx?ID=" + roomid, function (data) {
        $("#" + roomid).html(data);
    });
}(roomid))

As a matter of fact, since you're not using var, roomid is global. This probably undesirable. Instead you should do:

var roomid = $(this).attr("id");

This will create a new roomid for each iteration of the .each function that won't be shared -- this makes the closure unnecessary.

1 Comment

I had made roomid a global variable, it was declared outside the snippet of code :)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.