【问题标题】:Javascript "for" loop issue when using ajax, the loop has access even when condition is false使用ajax时的Javascript“for”循环问题,即使条件为假,循环也可以访问
【发布时间】:2023-03-26 05:47:02
【问题描述】:

使用 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.
          }
        });
      }
    });

我们做了简单而愚蠢的修复,但我们还没有发现为什么会发生这种情况,for循环如何,假设data.auctions.length = 3,打印0,1,2,3

【问题讨论】:

标签: javascript php laravel-5


【解决方案1】:

倒计时结束后会执行 downCount 回调。这意味着这不会立即执行。

因此,您的循环会不断增加“j”,这意味着一旦执行回调,“j”将处于最大值。

这是您所体验的简单演示。它将多次记录“5”,而不是 0、1、2、3、4。之所以为 5,是因为 i 会先递增,然后再检查条件! 这正是您的代码崩溃的原因。由于 j 最多比数组长度增加 1,因此要检查条件!

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 的范围界定文章是正确的。这是一本很好的读物,可以进一步启发您!

【讨论】:

  • 请使用内置的 StackSnippets 功能发布可运行的示例。这使得帖子自成一体并且更容易理解,而无需场外资源。如果站外链接碰巧停止工作,它还可以防止帖子失去价值。您可以使用[&lt;&gt;] 按钮创建一个可运行的sn-p。 Check here for more info.
  • 哦,感谢您的更新!我不知道!我会尽快更新我的答案。
猜你喜欢
  • 2014-03-30
  • 2017-07-26
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 2012-09-20
相关资源
最近更新 更多