3

I want to execute Ajax in a loop to fetch data one by one. I did something like this in my javascript function.

var resultType = $("input[name='resultType']:checked").val();
var finalResult = "";
var loadingMessage = "<img src=\"./results/loader.gif\" alt=\"Loading...\"/><br/>This may take several minutes...";
var htmlMessage=loadingMessage;

$("#result").html(htmlMessage);

for(var i=1;i<5;i++){
    $.ajax({
        type: "GET",
        url: "results/result_html.php?usn="+i+"&resultType="+resultType,
        dataType:"JSON",
        success:function(result){
            finalResult+=result;
            result=result+htmlMessage;
            $("#info").hide();
            $("#result").html(result);              
            $("#usn").attr("placeholder", "Class USN");
        }
    });
}

But it is not executing as I expected. If I remove for loop and give value directly then everything is proper. I'm not much familiar with Ajax. Please can anyone help me?

sdespont
  • 13,915
  • 9
  • 56
  • 97
Vishal Vijay
  • 2,518
  • 2
  • 23
  • 45
  • 1
    First of all; what do you expect? It seems the result will be overridden on every request now. – Chris Laarman Feb 26 '13 at 14:40
  • I want to get the result one after other. See `usn` is changing in each loop. I know it's wrong and I don't know how to make it correct. I want to concatenate each result with finalResult. – Vishal Vijay Feb 26 '13 at 14:45
  • You specify that you are expecting JSON data from the server, but you don't use the returned data as a JOSON map. Is it correct? – sdespont Feb 26 '13 at 14:47

2 Answers2

2

you are dealing with a common problem with closures. by the time your ajax request is executed, the counter "i" is already and always at it's last value (4).

you have to create a new scope for that counter, so that it doesn't happen; you can do it in two ways:

the easy way:

for(var i=1;i<5;i++){
    var counter = i;
    $.ajax({
        type: "GET",
        url: "results/result_html.php?usn="+counter+"&resultType="+resultType,
        dataType:"JSON",
        success:function(result){
            finalResult+=result;
            result=result+htmlMessage;
            $("#info").hide();
            $("#result").html(result);              
            $("#usn").attr("placeholder", "Class USN");
        }
    });
}

or the correct way:

for(var i=1;i<5;i++){
(function(counter){
    $.ajax({
        type: "GET",
        url: "results/result_html.php?usn="+"counter"+"&resultType="+resultType,
        dataType:"JSON",
        success:function(result){
            finalResult+=result;
            result=result+htmlMessage;
            $("#info").hide();
            $("#result").html(result);              
            $("#usn").attr("placeholder", "Class USN");
        }
    });
})(i);}
Vishal Vijay
  • 2,518
  • 2
  • 23
  • 45
André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120
2

I don't see a problem with closures in this code. I believe that what you are trying to achieve has to do with forcing a sequential load. The way you are currently proposing will issue all the ajax calls 'in parallel'. The problem relies in the asynchronous nature of an ajax call.

If you want to 'sequentialize' the requests, then you can do something like this:

var resultType =$("input[name='resultType']:checked").val();
var finalResult="";
var loadingMessage="<img src=\"./results/loader.gif\" alt=\"Loading...\"/><br/>This may   take several minutes...";
var htmlMessage=loadingMessage;
$("#result").html(htmlMessage);

var i = 1;

function loadNext(){
    if (i < 5){
        $.ajax({
            type: "GET",
            url: "results/result_html.php?usn="+i+"&resultType="+resultType,
            dataType:"JSON",
            success:function(result){
                finalResult+=result;
                result=result+htmlMessage;
                $("#info").hide();
                $("#result").html(result);              
                $("#usn").attr("placeholder", "Class USN");
                loadNext();
            }
        });
        i++;
    }
}
DanC
  • 8,595
  • 9
  • 42
  • 64