Reputation: 2138
Recently I was searching in internet for some code which can handle abandoned ajax/xhr calls.
$.xhrPool = [];
$.ajaxSetup({
beforeSend: function (jqXHR) {
$.xhrPool.push(jqXHR);
},
complete: function (jqXHR) {
var i = $.xhrPool.indexOf(jqXHR);
if (i > -1)
$.xhrPool.splice(i, 1);
}
});
$.xhrPool.abortAll = function () {
$(this).each(function (i, jqXHR) {
jqXHR.abort();
$.xhrPool.splice(i, 1);// This is the line which makes me confused.
});
};
This code works fine, but one line in it confuses me, I doubt that there is some logical error, but somehow works perfect.
Below is the part which confuses me,
$(this).each(function (i, jqXHR) {
$.xhrPool.splice(i, 1);
});
Iterating through a for loop and takes i'th element and removes it from array.
Now the total length of the array is reduced and the indexes of the elements also reduces, as first member is removed from it.
Then in the next iteration, value of i is increased, so the element which is getting cought will be different (or not as expected).
For example consider array = [1,2,3,4,5,6,7,8,9,10];
array = [1,2,3,4,5,6,7,8,9,10]
i=0
removes 1
new array is [2,3,4,5,6,7,8,9,10]
array = [2,3,4,5,6,7,8,9,10]
i=1
removes 3
new array is [2,4,5,6,7,8,9,10]
array = [2,4,5,6,7,8,9,10]
i=2
removes 5
new array is [2,4,6,7,8,9,10]
array = [2,4,6,7,8,9,10]
i=3
removes 7
new array is [2,4,6,8,9,10]
array = [2,4,6,8,9,10]
i=4
removes 9
new array is [2,4,6,8,10]
array = [2,4,6,8,10]
i=5
** Here comes the trouble.
Note : My computer is able to understand this code and execute it correctly, but the trouble is with my brain, who is not ready to accept this part :-(
I believe that the $.each is the one who makes the job correctly, but still I am not able to figure it how.
Upvotes: 2
Views: 558
Reputation: 350137
The code "works", but is not doing what it is supposed to do. The method is called abortAll
, and it does abort all XHRs, but only clears half of the array. It should really remove all items it aborts, which it doesn't.
jQuery each
will take a copy of the array and iterate that, so i will still go from 0 to the last index in the (copied) array, even though elements are removed from the original array.
But it still goes wrong, because the splice
acts on the original array, which moves elements to preceding indexes in that array. But i, on the other hand, keeps increasing, so one in two elements will survive the splice
.
The abortAll
could be corrected to this:
$.xhrPool.abortAll = function () {
$(this).each(function (i, jqXHR) {
jqXHR.abort();
// the element to be deleted will always be at index 0 in the original array:
$.xhrPool.splice(0, 1);
});
});
... but really, it can be done simply like this:
$.xhrPool.abortAll = function () {
$(this).each(function (i, jqXHR) {
jqXHR.abort();
});
$.xhrPool.length = 0;
});
Upvotes: 5