Thursday, June 18, 2009

asynchrone Ajax query problem

Can you find what's wrong in this code:

function example(event){
for(i = 1; i < array.length; i++){
new Ajax.Request(url, {
method: 'put',
postBody: someParam,
onSuccess: function(transport){
$(array[i]).innerHTML = "updated!";
},
onFailure: function(transport){
//do something
}
});
}
}

Description: let's say the array elements are all IDs of some tags "div". There is a loop, for each element an ajax request is send.
Hint: The "a" of Ajax stands for "asynchronous".
So where is the problem?

The problem is here:
$(array[i]).innerHTML = "updated!";

Why? Because we use "i"! Let's say the array has 10 elements. First (asynchronous) request is send (i=1), so our controller is working, and at the same time the loop continue, so now i=2, another Ajax request is send and so on. Now i=4 and... oh! the controller just finished is work for the first request, so the function onSucces is called, and then $(array[i]).innerHTML = "updated!". But "i" is 4 now! It's not 1 ! So we write "updated!" in the wrong div.

Here is my solution (maybe not the best one), I send "i" as a parameter to the controller and the controller return it.

function example(event){
for(i = 1; i < array.length; i++){
new Ajax.Request(url, {
method: 'put',
postBody: i, //send "i"
onSuccess: function(transport){
//get the response
original_i = transport.responseJSON;

$(array[original_i]).innerHTML = "updated!";
},
onFailure: function(transport){
//do something
}
});
}
}

Insuide the controller:

def my_controller
post_data = request.raw_post #here we received "i"
....
....
....
render :text => post_data #and we return it
end

No comments: