简体   繁体   中英

JQuery handles array out of index errors when $.each and array.splice(i) are kept together

Recently I was searching in internet for some code which can handle abandoned ajax/xhr calls.

And this is what I found :

$.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];

Iteration 1

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]

Iteration 2

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]

Iteration 3

array = [2,4,5,6,7,8,9,10]
i=2
removes 5
new array is [2,4,6,7,8,9,10]

Iteration 4

array = [2,4,6,7,8,9,10]
i=3
removes 7
new array is [2,4,6,8,9,10]

Iteration 5

array = [2,4,6,8,9,10]
i=4
removes 9
new array is [2,4,6,8,10]

Iteration 6

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.

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;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM