当前位置: 代码迷 >> JavaScript >> 你如何处理setTimeout()的多个实例?
  详细解决方案

你如何处理setTimeout()的多个实例?

热度:137   发布时间:2023-06-13 12:48:21.0

阻止创建setTimeout函数的多个实例的最佳推荐/最佳方法是什么(在javascript中)?

一个例子(伪代码):

function mouseClick()
{
   moveDiv("div_0001", mouseX, mouseY);
}

function moveDiv(objID, destX, destY)
{
   //some code that moves the div closer to destination
   ...
   ...
   ...

   setTimeout("moveDiv(objID, destX, destY)", 1000);
   ...
   ...
   ...
}

我的问题是如果用户多次点击鼠标,我会调用多个moveDiv()实例。

我看到的选项是创建一个标志,只允许在没有其他实例可用的情况下调用超时...这是最好的方法吗?

我希望说清楚......

当你调用settimeout时,它会返回一个变量“handle”(一个数字,我认为)

如果你第二次调用settimeout,你应该先

clearTimeout( handle )

然后:

handle = setTimeout( ... )

为了帮助自动执行此操作,您可以使用将超时调用与字符串相关联的包装器(即div的id或您想要的任何内容),这样如果之前的settimeout具有相同的“字符串”,它会自动为您清除它重新设置,

您将使用数组(即字典/散列映射)将字符串与句柄相关联。

var timeout_handles = []    
function set_time_out( id, code, time ) /// wrapper
{
    if( id in timeout_handles )
    {
        clearTimeout( timeout_handles[id] )
    }

    timeout_handles[id] = setTimeout( code, time )
}

当然还有其他方法可以做到这一点..

我会这样做:

// declare an array for all the timeOuts
var timeOuts = new Array();  

// then instead of a normal timeOut call do this
timeOuts["uniqueId"] = setTimeout('whateverYouDo("fooValue")', 1000);  

// to clear them all, just call this
function clearTimeouts() {  
  for (key in timeOuts) {  
    clearTimeout(timeOuts[key]);  
  }  
}  

// clear just one of the timeOuts this way
clearTimeout(timeOuts["uniqueId"]); 

我没有测试任何这个,只是在编辑器中将其剪切掉。 可能会工作,可能不会,希望这会让人深思。

var Timeout = { 
   _timeouts: {}, 
   set: function(name, func, time){ 
     this.clear(name); 
     this._timeouts[name] = {pending: true, func: func}; 
     var tobj = this._timeouts[name];
     tobj.timeout = setTimeout(function()
     { 
/* setTimeout normally passes an accuracy report on some browsers, this just forwards that. */
       tobj.func.call(arguments); 
       tobj.pending = false;
     }, time); 
   },
   hasRun: function(name)
   { 
       if( this._timeouts[name] ) 
       {
          return !this._timeouts[name].pending; 
       }
       return -1; /* Whut? */ 
   },
   runNow: function(name)
   {
      if( this._timeouts[name] && this.hasRun(name)===false )
      {
         this._timeouts[name].func(-1); /* fake time. *shrug* */
         this.clear(name);
      }
   } 
   clear: function(name)
   {
     if( this._timeouts[name] && this._timeouts[name].pending ) 
     {
       clearTimeout(this._timeouts[name].timeout); 
       this._timeouts[name].pending = false; 
     }
   }
};

Timeout.set("doom1", function(){ 
  if(  Timeout.hasRun("doom2") === true )
  {
     alert("OMG, it has teh run");  
  }
}, 2000 ); 
Timeout.set("doom2", function(){ 
   /* NooP! */
}, 1000 ); 

具有相同标识符的连续呼叫将取消之前的呼叫。

您可以使用objID作为键在查找表(哈希)中存储多个标志。

var moving = {};

function mouseClick()
{
  var objID = "div_0001";
  if (!moving[objID])
  {
    moving[objID] = true;
    moveDiv("div_0001", mouseX, mouseY);
  }
}

您可以通过在函数中使用属性来避免全局变量或较小变量。 如果该函数仅用于此特定上下文,则此方法很有效。

function set_time_out( id, code, time ) /// wrapper
{
  if(typeof this.timeout_handles == 'undefined') this.timeout_handles = [];

        if( id in this.timeout_handles )
        {
                clearTimeout( this.timeout_handles[id] )
        }

        this.timeout_handles[id] = setTimeout( code, time )
}

我正在使用它来强制所有过时的超时引用上的垃圾收集,这些引用确实没有落后于我的脚本性能:

var TopObjList = new Array();
function ColorCycle( theId, theIndex, RefPoint ) {
    ...
    ...
    ...
    TopObjList.push(setTimeout( function() { ColorCycle( theId, theIndex ,CCr ); },CC_speed));
    TO_l = TopObjList.length;
    if (TO_l > 8888) {
        for (CCl=4777; CCl<TO_l; CCl++) {
            clearTimeout(TopObjList.shift());
            }
        }
    }

我最初的草率代码在非常短的时间内生成了一个超过100,000个深度的巨大阵列,但这真的很有用!

var timeout1 = window.setTimeout('doSomething();', 1000);
var timeout2 = window.setTimeout('doSomething();', 1000);
var timeout3 = window.setTimeout('doSomething();', 1000);

// to cancel:
window.clearTimeout(timeout1);
window.clearTimeout(timeout2);
window.clearTimeout(timeout3);

您可以随时覆盖按钮onclick返回false。 例:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="UTF-8">
<head>
    <title>Javascript example</title>
    <script type="text/javascript">         
        var count = 0;
        function annoy() {
            document.getElementById('testa').onclick = function() { return false; };

            setTimeout(function() {
                alert('isn\'t this annoying? ' + count++);
                document.getElementById('testa').onclick = window.annoy;
            }, 1000);

        }
    </script>
</head>
<body>
    <h2>Javascript example</h2>
    <a href="#" onClick="annoy()" id="testa">Should Only Fire Once</a><br />
</body>
</html>

您可以在某处设置一个全局标志(如var mouseMoveActive = false;),告诉您是否已经在呼叫中,如果是,则不启动下一个。 在检查是否已设置后,在进入setTimeout调用之前设置标志。 然后在setTimeout()中调用的例程结束时,您可以重置该标志。