在 if 循环中使用 setTimeout 时捕获 setTimeout timerID

capture setTimeout timerID when setTimeout is used in an if loop

我正在使用 setTimeout 在循环中创建一个暂停(在 mouseenter 上)并且需要捕获计时器 ID 以便它可以在 mouseleave 上停止。

我认为这将是一项简单的任务……在我尝试编写代码之前。

我有一个缩略图画廊,将鼠标悬停在缩略图上时,我想循环浏览一系列图像(无限循环);有点像迷你旋转木马。我通过交换缩略图的源文件路径的常用方法来实现这一点;我捕获并存储缩略图的文件路径,循环遍历一组图像,然后在 mouseleave 上替换原始缩略图。没什么复杂的。

我对此进行了编码,一切正常,除了 mouseenter 函数循环遍历整个图像数组,无论鼠标悬停的时间有多短。我最终发现你实际上不能暂停或停止一个函数,但是通过将它包装在一个 setTimeout 中并使用一个布尔标志,你可以创建那个效果。这是我从 user1693593 找到的答案,它非常简单而且效果很好。

    var doLoop = false;

    function loopy() {
        if (doLoop === true) {
            setTimeout(function () {
            // code to loop through array of images
            loopy();
            }, 11);
        }
    };

我正在使用 jQuery 的悬停方法来设置标志。

    $(".thumbnails").hover(function() {
        doLoop = true;
    }, function() {
        doLoop = false;
    });

所以我把它编码了,当你将鼠标悬停在第一个缩略图上时,它工作得很好,但当你移动到一个新的缩略图时,一切都变得一团糟。我发现这是因为第一个超时没有被取消,随后的超时干扰了它(以及彼此)。我从各种 Stack Overflow 问题中可以看出这是一个常见问题。我发现 setTimeout returns 一个 ID,如果你想用 clearTimeout 取消它,你需要捕获它。

所以我在 MDN setInterval 上找到了一个示例,您可以将超时 ID 存储在一个变量中。它看起来很简单,所以我将其编码并完美运行。当鼠标在缩略图上移动时,我可以在控制台中看到所有超时设置(具有唯一 ID)和取消……但现在我无法让循​​环工作。

我不明白为什么在 JavaScript 中这么复杂,这肯定是常见的需求。

有人可以可怜一下相关的新手,并解释我如何编写 user1693593 的示例代码,以便在将鼠标悬停在多个元素上时它能正常工作。我不介意它使用setTimeout还是setInterval。

请不要将其标记为重复——如果有人这样做我会理解的——但我已经遍历 Stack Overflow(加上 MDN 和 W3Schools)但我找不到具体回答这个问题的例子问题,肯定不是我能理解的问题。

将引用存储在某处并取消它。

var timer = null

function addOne (elem) {
  elem.textContent = (+elem.textContent + .1).toFixed(1)
}


$(".foo")
  .on("mouseenter", function () {
    var elem = this
    timer = window.setInterval(function () { addOne(elem) }, 100)
  }).on("mouseleave", function () {
    if (timer) window.clearInterval(timer)
  })
div.foo {
  width:100px;
  line-height: 100px;
  border: 1px solid black;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="foo">1</div>
<div class="foo">1</div>
<div class="foo">1</div>
<div class="foo">1</div>
<div class="foo">1</div>

只需跟踪当前正在执行循环的元素而不是布尔值 true/false。

var loopEl;

function loopy() {
    if (loopEl) {
        setTimeout(function () {
        // code to loop through array of images
        // do something with loopEl
        loopy();
        }, 11);
    }
};

$(".thumbnails").hover(function() {
    loopEl = this;
}, function() {
    loopEl = false;
});