JavaScript for循环搭配AJAX回调索引异常:5条购物车行控制台输出6如何解决
问题原因
- 循环条件错误:当前循环条件为
indexCount <= cartRows,若有5条购物车行,cartRows值为5,合法索引范围是0~4,循环会多执行一次到indexCount=5,是索引值异常的基础诱因。 - 异步回调闭包陷阱:AJAX为异步请求,success回调执行时for循环已经全部执行完毕,全局作用域下的
indexCount已经是循环结束后的最终值,不会保留每次循环的对应索引,所有回调获取到的都是同一个最终的indexCount值。
解决方案
调整循环条件,同时用块级作用域保留每次循环的索引值即可解决,修改后的代码如下:
$('.up-cart').on('click', function() { const cartRows = $('.cartRows').length; // 修正循环条件为<,用let声明块级作用域的索引变量 for (let indexCount = 0; indexCount < cartRows; indexCount++) { // 变量声明移到循环内部,避免全局污染和值串用 let selectedColor = ''; let selectedSize = ''; let selectedQuantity = ''; let productID = ''; $('.myOrderSettings [name="selectedColor' + indexCount + '"]').each(function() { if ($(this).prop("checked")) { selectedColor = selectedColor ? `${selectedColor},${$(this).val()}` : $(this).val(); } }); $('.myOrderSettings [name="selectedSize' + indexCount + '"]').each(function() { if ($(this).prop("checked")) { selectedSize = selectedSize ? `${selectedSize},${$(this).val()}` : $(this).val(); } }); $('.myOrderSettings [name="selectedQuantity' + indexCount + '"]').each(function() { const curVal = parseInt($(this).val()); const maxVal = parseInt($(this).attr('max')); if (curVal < 1) { selectedQuantity = '1'; alertMe("Your order quantity has been set to 1", 5000); } else if (curVal > maxVal) { selectedQuantity = $(this).attr('max'); alertMe(`We have ${maxVal} of this product. Your order quantity has been set to ${maxVal}`, 5000); } else { selectedQuantity = $(this).val(); } }); productID = $('.myOrderSettings [name="productID' + indexCount + '"]').val(); $.ajax({ url: "<?php echo base_url() ?>cart/updateCart", type: "post", dataType: "json", data: { selectedColor, selectedSize, selectedQuantity, productID }, success: function(data) { console.log(indexCount); $('.myOrderSettings .t-total' + indexCount).html(formatMoney(parseInt(data.cart_amount))); calculateTotalAmount(); } }); } });
如果需要兼容不支持ES6 let语法的低版本浏览器,可使用立即执行函数(IIFE)保留每次循环的索引,将循环内的AJAX部分替换为如下写法即可:
(function(currentIndex) { $.ajax({ // 其他配置保持不变 success: function(data) { console.log(currentIndex); $('.myOrderSettings .t-total' + currentIndex).html(formatMoney(parseInt(data.cart_amount))); calculateTotalAmount(); } }); })(indexCount);
内容的提问来源于stack exchange,提问作者Foozaweb
相关产品推荐
相关产品推荐

