JQuery обрабатывает массив из ошибок индекса, когда $.each и array.splice(i) сохраняются вместе
Недавно я искал в Интернете какой-то код, который может обрабатывать заброшенные вызовы ajax/xhr.
И вот что я нашел:
$.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).each(function (i, jqXHR) {
$.xhrPool.splice(i, 1);
});
Итерация через цикл for и принимает i-й элемент и удаляет его из массива.
Теперь общая длина массива уменьшается, а индексы элементов также уменьшаются, поскольку первый элемент удаляется из него.
Затем в следующей итерации значение я увеличивается, поэтому элемент, который получает кучу, будет отличаться (или не так, как ожидалось).
Например, рассмотрим массив = [1,2,3,4,5,6,7,8,9,10];
Итерация 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]
Итерация 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]
Итерация 3
array = [2,4,5,6,7,8,9,10]
i=2
removes 5
new array is [2,4,6,7,8,9,10]
Итерация 4
array = [2,4,6,7,8,9,10]
i=3
removes 7
new array is [2,4,6,8,9,10]
Итерация 5
array = [2,4,6,8,9,10]
i=4
removes 9
new array is [2,4,6,8,10]
Итерация 6
array = [2,4,6,8,10]
i=5
** Здесь возникает проблема.
Примечание. Мой компьютер способен понять этот код и выполнить его правильно, но проблема с моим мозгом, который не готов принять эту часть: - (
Я считаю, что $.each - это тот, кто правильно выполняет задание, но все же я не могу понять, как это сделать.
Ответы
Ответ 1
Код "работает", но не выполняет то, что он должен делать. Метод называется abortAll
, и он отменяет все XHR, но только очищает половину массива. Он должен действительно удалить все элементы, которые он прерывает, а это не так.
jQuery each
возьмет копию массива и повторит ее, поэтому я все равно перейду от 0 к последнему индексу в (скопированном) массиве, даже если элементы будут удалены из исходного массива.
Но это по-прежнему не так, потому что splice
действует на исходный массив, который перемещает элементы в предыдущие индексы в этом массиве. Но i, с другой стороны, продолжает расти, поэтому один из двух элементов выдержит splice
.
abortAll
может быть исправлено:
$.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);
});
});
... но на самом деле это можно сделать просто так:
$.xhrPool.abortAll = function () {
$(this).each(function (i, jqXHR) {
jqXHR.abort();
});
$.xhrPool.length = 0;
});