setTimeout / clearTimeout问题


103

我尝试使页面转到例如eg之后的首页。10秒钟不活动(用户未单击任何位置)。我使用jQuery进行其余操作,但测试功能中的set / clear是纯javascript。

令我沮丧的是,我最终得到了类似该功能的东西,希望我可以在该页面上进行任何单击。计时器可以正常启动,但单击后不会重置。如果在前10秒内调用该函数5次,则将出现5条警报...无clearTimeout ...

function endAndStartTimer() {
    window.clearTimeout(timer);
    var timer;
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

有人得到一些可以解决问题的代码行吗?-在任何点击停止时,重置并启动计时器。-当计时器命中时 10sec做点什么。

Answers:


226

您需要在函数timer 外部声明。否则,您将在每次函数调用时获得一个全新的变量。

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

加1,因为在这种情况下有必要在调用超时之前清除带有timeOut的变量,这样就避免了两次调用它
Diego Favero

46

问题在于该timer变量是局部变量,并且在每个函数调用之后其值都会丢失。

您需要持久化它,可以将其放在函数外部,或者如果您不想将变量公开为全局变量,则可以将其存储在闭包中,例如:

var endAndStartTimer = (function () {
  var timer; // variable persisted here
  return function () {
    window.clearTimeout(timer);
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
  };
})();

15

这是因为timer是函数的局部变量。

尝试在函数外部创建它。


6

在反应中使用此方法:

class Timeout extends Component {
  constructor(props){
    super(props)

    this.state = {
      timeout: null
    }

  }

  userTimeout(){
    const { timeout } = this.state;
    clearTimeout(timeout);
    this.setState({
      timeout: setTimeout(() => {this.callAPI()}, 250)
    })

  }
}

例如,如果您只想在用户停止输入后才调用API,则该功能非常有用。可以通过onKeyUp将userTimeout函数绑定到输入。


1
谢谢,这就是我一直在寻找的几个小时。我只是想知道是否有更好的方法来实现这种结果?
Nikasv

1
@nikasv节流和反跳是两种选择:medium.com/@
jh3y

2

不知道这是否违反了一些好的惯例编码规则,但我通常会提出以下规则:

if(typeof __t == 'undefined')
        __t = 0;
clearTimeout(__t);
__t = setTimeout(callback, 1000);

这避免了需要从函数中声明计时器。

编辑:这也不会在每次调用时声明一个新变量,但始终循环使用相同的变量。

希望这可以帮助。


0

这很好。我是负责处理保持事件的经理。有要保留的事件以及您放手的事件。

function onUserHold(element, func, hold, clearfunc) {
    //var holdTime = 0;
    var holdTimeout;

    element.addEventListener('mousedown', function(e) {
        holdTimeout = setTimeout(function() {
            func();
            clearTimeout(holdTimeout);
            holdTime = 0;
        }, hold);
        //alert('UU');
    });

    element.addEventListener('mouseup', clearTime);
    element.addEventListener('mouseout', clearTime);

    function clearTime() {
        clearTimeout(holdTimeout);
        holdTime = 0;
        if(clearfunc) {
            clearfunc();
        }
    }
}

element参数是您持有的那个。当func参数保持由参数hold指定的毫秒数时,它将触发。clearfunc参数是可选的,如果给定,则如果用户放开或离开该元素,它将被触发。您也可以采取一些变通方法来获得所需的功能。请享用!:)


0

实际示例使用Jquery下拉菜单!将鼠标悬停在#IconLoggedinUxExternal上会显示div#ExternalMenuLogin,并设置超时以隐藏div#ExternalMenuLogin

将鼠标悬停在div#ExternalMenuLogin上可取消超时。在div#ExternalMenuLogin上单击鼠标时,它将设置超时。

这里的重点始终是在设置超时之前调用clearTimeout,这样可以避免重复调用

var ExternalMenuLoginTO;
$('#IconLoggedinUxExternal').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
    $("#ExternalMenuLogin").show()
});

$('#IconLoggedinUxExternal').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )    
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,1000
    );
    $("#ExternalMenuLogin").show()
});

$('#ExternalMenuLogin').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
});
$('#ExternalMenuLogin').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,500
    );
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.