使用javascript在循环内设置超时

Posted

技术标签:

【中文标题】使用javascript在循环内设置超时【英文标题】:Setting timeout inside loop with javascript 【发布时间】:2020-03-01 05:05:30 【问题描述】:

我正在制作一个解谜功能,该功能使用当前打乱顺序的一组拼图。每个部分都有一个 id,它指向数组中的正确位置。我在即将交换的部分上设置了叠加颜色。我希望在着色和交换的部分之间有一个延迟。

function solvePuzzle() 
    while (rezolvat == false) // while all pieces are not in correct position
        for (var i = 0; i < _piese.length; i++)  // iterates through array of puzzle pieces
            if (checkPiesa(i) == false) 
                _piesaCurentaDrop = _piese[i];
                _piesaCurenta = getPiesaDestinatie(_piesaCurentaDrop.id); // destination piece
                _context.save();
                _context.globalAlpha = .4;
                _context.fillStyle = PUZZLE_HOVER_TINT;
                _context.fillRect(_piesaCurentaDrop.xPos, _piesaCurentaDrop.yPos, _latimePiesa, _inaltimePiesa);
                _context.fillStyle = PUZZLE_DESTINATION_HOVER_TINT;
                _context.fillRect(_piesaCurenta.xPos, _piesaCurenta.yPos, _latimePiesa, _inaltimePiesa);
                _context.restore();

                // here I want to have some kind of 'sleep' for 2000 ms so you can see the pieces about to be swapped
                dropPiece(); // function for swapping puzzle pieces
            
        

【问题讨论】:

你能把dropPiece换成超时吗?类似setTimeout(() =&gt; dropPiece(), 2000); 【参考方案1】:

你可以使用javascriptsetTimeout()函数,它会在指定的毫秒后执行该函数,你可以了解更多关于它here

function solvePuzzle() 
  while (rezolvat == false) // while all pieces are not in correct position
    for (var i = 0; i < _piese.length; i++)  // iterates through array of puzzle pieces
      (function (i) 
        setTimeout(function () 

          if (checkPiesa(i) == false) 
            _piesaCurentaDrop = _piese[i];
            _piesaCurenta = getPiesaDestinatie(_piesaCurentaDrop.id); // destination piece
            _context.save();
            _context.globalAlpha = .4;
            _context.fillStyle = PUZZLE_HOVER_TINT;
            _context.fillRect(_piesaCurentaDrop.xPos, _piesaCurentaDrop.yPos, _latimePiesa, _inaltimePiesa);
            _context.fillStyle = PUZZLE_DESTINATION_HOVER_TINT;
            _context.fillRect(_piesaCurenta.xPos, _piesaCurenta.yPos, _latimePiesa, _inaltimePiesa);
            _context.restore();

            // here I want to have some kind of 'sleep' for 2000 ms so you can see the pieces about to be swapped
            // setTimeout in side task execution
            setTimeout(() => dropPiece(), 1000); // function for swapping puzzle pieces
          
        , 2000 * i); // schedules excution increasingly for each iteration
      )(i);
    

在上面的代码中,for循环立即结束,但是,它使用setTimeout在指定的增加时间(i*2000)之后安排每次迭代的执行

所以执行,(尽管 for 循环立即完成)

第一次迭代将在 0*2000=0 毫秒后立即开始,

第二次执行的任务将在(1*2000)之后执行,

第三次执行的任务会在(2*2000)之后执行,

等等..

只是为了简单理解看下面的示例代码

工作代码示例

for (var i = 0; i < 5; i++) 
  (function(i) 
    setTimeout(function() 
      console.log(i);
      setTimeout(() => console.log(i + 0.5), 1000); // setTimeout in side task execution in case needed
    , 2000 * i); // schedules excution increasingly for each iteration
  )(i);

【讨论】:

我之前尝试过,它与 js 中的 sleep 最接近,但不是我想要的。问题是 dropPiece() 函数的超时并不能阻止 for 继续执行新的迭代,因此它在交换旧的之前移动到新的部分。 你的dropPiece函数是异步的吗? 不,它不是异步的。 它与之前使用 setTimeout() 的行为相同,它继续 for 迭代。现在我正在尝试使用带有承诺的 async/await 来模拟我需要的睡眠。它在第一次迭代时确实有效,但随后意外退出。 它不能和前一个有相同的行为,请检查twise,它为每次迭代设置了增加的超时,所以第一次迭代的任务将在2秒后执行。第二次迭代的任务将在 4 秒后执行,依此类推

以上是关于使用javascript在循环内设置超时的主要内容,如果未能解决你的问题,请参考以下文章

h5设置请求超时时间

循环中的javascript var声明

Parse.com 从客户端批量保存 (saveAll) 超时

html+css+javascript实现列表循环滚动示例代码

如何为 MFC 线程设置超时

关于Java线程超时退出的问题.