当 $.each 和 array.splice(i) 保持在一起时,JQuery 处理数组超出索引错误
Posted
技术标签:
【中文标题】当 $.each 和 array.splice(i) 保持在一起时,JQuery 处理数组超出索引错误【英文标题】:JQuery handles array out of index errors when $.each and array.splice(i) are kept together 【发布时间】:2018-01-12 00:25:39 【问题描述】:最近我在网上搜索一些可以处理废弃的 ajax/xhr 调用的代码。
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).each(function (i, jqXHR)
$.xhrPool.splice(i, 1);
);
遍历 for 循环并获取第 i 个元素并将其从数组中删除。
现在数组的总长度减少了,元素的索引也减少了,因为第一个成员被从中删除了。
然后在下一次迭代中,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
将获取数组的副本并对其进行迭代,因此 i 仍将从 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;
);
【讨论】:
感谢您的回复。您的第二种方法有一个小缺点,它会重新初始化数组,因此 abortAll 方法将从数组中删除,我们将不得不再次重新初始化它以将方法附加到数组中。 确实,我已经更新了答案以避免重新初始化。 现在完美了:)以上是关于当 $.each 和 array.splice(i) 保持在一起时,JQuery 处理数组超出索引错误的主要内容,如果未能解决你的问题,请参考以下文章