与laravel一起使用时,我们正在开发的系统在“ onready”事件上因该视图而崩溃。查看代码后,我们发现问题出在for循环内。
$(document).ready(function() {
var url = "{{ route('routeToGetAuctions') }}";
$.ajax({
url : url,
type : "GET"
})
.done(function(data) {
for (var j = 0; j < data.auctions.length; j++) {
...
$('#object').downCount(data.auctions[j].auction, {
startDate: data.auctions[j].startDate,
endDate: data.auctions[j].endDate,
offset: data.auctions[j].offset
}, function() {
//Class management to show the auctions
finishedAuctions.push(data.auctions[j].auction);
$('#countdown-bg-'+data.auctions[j].auction).removeClass('bg-primary');
$('#countdown-bg-'+data.auctions[j].auction).addClass('bg-secondary');
$('#progress-'+data.auctions[j].auction).removeClass('bg-primary');
$('#progress-'+data.auctions[j].auction).addClass('bg-secondary');
});
}
});
这非常适合我们的需求...但是,假设存在3个可用的竞价,data.auctions.length
的值将为3,并执行console.log('value of j: ' + j)
调试for循环,打印:
value of j: 0
value of j: 1
value of j: 2
value of j: 3
,然后在尝试到达大小为3(0,1,2)的数组的索引3时崩溃。
我们进行的伪修复是一个 try catch 代码块,因为无论数组中存在多少项并且始终到达最后一个索引+ 1,该问题仍然存在。
$(document).ready(function() {
var url = "{{ route('routeToGetAuctions') }}";
$.ajax({
url : url,
type : "GET"
})
.done(function(data) {
for (var j = 0; j < data.auctions.length; j++) {
...
$('#object').downCount(data.auctions[j].auction, {
startDate: data.auctions[j].startDate,
endDate: data.auctions[j].endDate,
offset: data.auctions[j].offset
}, function() {// Try Catch to fix unknown problem with loop
try {
finishedAuctions.push(data.auctions[j].auction);
$('#countdown-bg-'+data.auctions[j].auction).removeClass('bg-primary');
$('#countdown-bg-'+data.auctions[j].auction).addClass('bg-secondary');
$('#progress-'+data.auctions[j].auction).removeClass('bg-primary');
$('#progress-'+data.auctions[j].auction).addClass('bg-secondary');
} catch (e) {
//here the index exception is prevented and the view won't crash.
}
});
}
});
我们进行了简单而愚蠢的修复,但是我们还没有发现为什么会这样,假设data.auctions.length = 3
,打印0,1,2,3
,for循环如何?
答案 0 :(得分:1)
倒计时完成后,将执行downCount回调。这意味着不会立即执行此操作。
因此,您的循环会不断增加“ j”,这意味着一旦执行了回调,“ j”将达到最大值。
这里是您正在经历的简单演示。它将多次记录为“ 5”,而不是0、1、2、3、4。之所以为5,是因为i首先递增,然后再检查条件! 这正是代码崩溃的原因。由于j最多增加一个比数组长度大的值,因此请检查条件!
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
}, 100)
}
最简单的解决方案是使用let
而不是var
,因为它们受范围限制。
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
}, 100)
}
如果您无权访问let
,则可以使用闭包
for (var i = 0; i < 5; i++) {
(function(val) {
setTimeout(function() {
console.log(val)
}, 100)
})(i)
}
@Vlaz的范围界定文章是正确的。这是一本很棒的书,可以进一步启发您!