the problem about jquery$.ajax in "for" loop
I use $.ajax to read xml info in "for" loop
here is my xml file:
<application>
<app id="id-1">
<html_code>
<div id="id-1" class="portlet">
<div class="portlet-header"Links</div>
<div class="portlet-content">id-1</div>
</div>
</html_code>
</app>
<app id="id-2">
<html_code>
<div id="id-2" class="portlet">
<div class="portlet-header"Links</div>
<div class="portlet-content">id-2</div>
</div>
</html_code>
</app>
<application>
then I use $.ajax to get the content in tags ,and prepend to a contain in this page here is the js code:
$.ajax({
……
success:function(){
for (var i = 0; i < $children.length; i++) {
var $temp_id = $children.eq(i).attr("id"); //"$children" have defined in above
$.ajax({
type: "get",
url: "Database/App_all.xml",
dataType: "html",
success: function (xml) {
开发者_StackOverflow var $temp_code = $(xml).find("app[id='" + $temp_id + "']").find("html_code").html();
$($temp_code).appendTo($("#contain")).hide().show('slow');
},
error: function () { }
});
}
}
});
suppose the $children.length is only 2,so the resault is that in the contain <div id="contain">
there should have <div class="portlet-content">id-2</div>
and <div class="portlet-content">id-1</div>
but the resault is that in <div id="contain">
only have one kind ,is <div class="portlet-content">id-2</div>
what's wrong with this ?
but when I write the alert(""); between for (var i = 0; i < $layout_left_children.length; i++) {
andvar $temp_id = $layout_left_children.eq(i).attr("id");
like
for (var i = 0; i < $children.length; i++) {
alert($children.eq(i).attr("id")); //could alert correct "id",first "id-1", then "id-2"
var $temp_id = $children.eq(i).attr("id"); //"$children" have defined in above
then the contain could be right as
So why could this happened? how can I solve this problem?
thank you:)
I believe there are a couple of things happening. First, the $temp_id variable is getting hoisted to the top of the function, so it's equivalent to doing this:
$.ajax({
……
success:function(){
var $temp_id;
for (var i = 0; i < $children.length; i++) {
$temp_id = $children.eq(i).attr("id");
Secondly, even though $temp_id is equal to "id-1" in the first loop, it gets changed to "id-2" in your second loop, so by the time your success callback is called for the first time, it's already been changed to "id-2".
This should solve your problem:
UPDATED 2010-12-03: fixed a bug
$.ajax({
……
success:function(){
for (var i = 0; i < $children.length; i++) {
var $temp_id = $children.eq(i).attr("id"); //"$children" have defined in above
$.ajax({
type: "get",
url: "Database/App_all.xml",
dataType: "html",
success: function($tid) {
return function (xml) {
var $temp_code = $(xml).find("app[id='" + $tid + "']").find("html_code").html();
$($temp_code).appendTo($("#contain")).hide().show('slow');
}
}($temp_id),
error: function () { }
});
}
}
});
What I'm doing is passing in $temp_id to the function that returns another function, which will be called in the success callback. It's now safe to use $tid in your success callback because it won't be impacted when $temp_id changes in the second loop.
UPDATE: Response to hh54188's comment below
Using "alert" can break the execution process and allow ajax callbacks to be called unexpectedly. This is the case in IE and Firefox. Chrome on the other hand doesn't behave like this. To test this, you can run this code:
for (var i = 0; i < 2; i++) {
//if (i == 1) alert('stopping execution');
console.log('loop: ' + i);
$.ajax({
url: "Database/App_all.xml",
dataType: "html",
success: function () {
console.log('callback');
}
});
}
You'll see that the output in the console is:
loop: 0
loop: 1
callback
callback
Now uncomment the line with the alert. In Firefox and IE, you'll see that the output in the console is now:
loop: 0
callback
loop: 1
callback
The first callback gets called while the alert box is displayed. The alert has essentially changed the behavior of your code. Using "alert" can be a source of frustration while developing in JavaScript because it can cause code execution to be unpredictable. Because of this, I don't recommend the use of "alert" while debugging. Instead, it's a lot more predictable to use console.log(). console.log() works in all modern browsers and IE 8+. For older IE, you'll want to output text into the DOM.
I think this is due to the aynchronous nature of AJAX request. Try setting the async
attribute to false
.
Note
synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
精彩评论