【问题标题】:Cancel a timed loop in JavaScript?取消 JavaScript 中的定时循环?
【发布时间】:2009-10-28 15:43:22
【问题描述】:

我正在尝试在JavaScript 中设置一个函数来淡入或淡出我页面上的某些元素。淡入淡出本身工作正常,但是当其中一个试图取消另一个的动作时,我的问题就出现了。

//I know this is ugly, I'm just learning JavaScript again and plan to recode it after I learn some more...
var fadeOut = false

//set out to true to fade out, false to fade in
function fade(out) {
    var steps = 1
    var outSpeed = 100
    var inSpeed = 10
    var timer = 0

    if (out) {
            //fade out
            fadeOut = true
            for ( var i=100; i>=0; i-=steps ) {
                    if ( fadeOut ) {
                            setTimeout("set_el_opacity(" + (i / 100) + ")",
                            timer+=steps
                    } else {
                            break;
                    }
            }
    } else {
            //fade in
            fadeOut = false
            for ( var i=0; i<=100; i+=steps ) {
                    if( !fadeOut ) {
                            setTimeout("set_el_opacity(" + (i / 100) + ")",
                            timer+=steps
                    } else {
                            break;
                    }
            }
    }
}

现在,淡出设置为比淡入慢。我希望用户看到它慢慢淡出,以便他们知道这是故意的,然后在需要元素时快速淡入(消除一些混乱不需要时从屏幕上显示)。

fade(true) 工作正常,fade(false) 工作正常并且速度更快。当我调用fade(true) 后不久调用fade(false) 时,我的问题就出现了。淡入淡出相互争斗,然后,由于淡出(true) 调用运行得更快,它首先完成,淡出淡出(false) 调用继续将其全部淡出。

我的问题是:我可以做些什么来使淡化(假)调用取消淡化(真)调用的循环?

【问题讨论】:

  • 提示:切勿将字符串作为参数传递给setTimeout/setInterval。如果您在生产中使用它,您的站点可能容易受到XSS 的攻击。请改用匿名函数setTimeout(function() { set_el_opacity(i / 100); }, 1000);

标签: javascript multithreading loops break


【解决方案1】:

当你设置定时器时:

mytime = setTimeout('function()', 1000);

您可以使用 clearTimeout 取消它:

clearTimeout(mytime);

【讨论】:

  • 谢谢,这回答了我的问题。下面对 setInterval 的评论让我知道我应该重新编写代码以以不同的方式更高效地运行。
【解决方案2】:

首先,在一个循环中触发许多计时器并不是一个好主意。您应该改用 setInterval 或从您的 setTimeout 处理程序中启动一个新计时器。

另一种方法是使用一个计时器,它以固定的时间间隔触发并管理所有待处理的效果。您可以决定帧速率并让您的计时器(“计时器堆栈”)无限期地运行,在每一帧“滴答”——当没有待处理的效果时,您可以选择启动/停止滴答。

【讨论】:

  • 这是我需要意识到的。我正在修改我在网上找到的一些代码,并没有意识到 setTimeout 函数会立即返回。所以基本上这个循环是设置大约 100 个较长间隔的计时器,然后让它们触发。我可以将它们分配给一个数组并将它们全部取消,或者更好的是,重新编写代码以正确查看。谢谢
【解决方案3】:

无论何时调用fade(),您都应该使用clearTimeout() 函数取消活动超时。有关超时的更多信息,请查看this article。这是基于您提供的代码的简短示例。

var timeoutId = null;

function fade(out) {
    // ...
    // Your variable declarations
    // ...

    // Cancel the active timeout, if any.
    clearTimeout(timeoutId);

    // Record the timeout ID inside your if-else blocks
    if (out) {
        // ...
        timeoutId = setTimeout( ... );
        // ...
    } else {
        // ...
        timeoutId = setTimeout( ... );
        // ...
    }
}

【讨论】:

【解决方案4】:

处理超时循环的最简单方法

function myFunc (terminator = false) {
    if(terminator) {
        clearTimeout(timeOutVar);
    } else {
        // do something
        console.log("loop");
        timeOutVar = setTimeout(function(){myFunc();}, 1000);
    }
}   
myFunc(true); //  -> start loop
myFunc(false); //  -> end loop

【讨论】:

    猜你喜欢
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多