Как вы обрабатываете несколько экземпляров setTimeout ()? - PullRequest
21 голосов
/ 24 ноября 2008

Каков наиболее рекомендуемый / лучший способ остановить создание нескольких экземпляров функции 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 ().

Опция, которую я видел, заключается в создании флага, который позволяет вызывать тайм-аут только в том случае, если другой экземпляр недоступен ... это лучший способ?

Надеюсь, это проясняет ....

Ответы [ 9 ]

27 голосов
/ 24 ноября 2008

когда вы вызываете settimeout, он возвращает вам переменную «handle» (число, я думаю)

если вы вызываете settimeout во второй раз, вы должны сначала

clearTimeout( handle )

, то:

handle = setTimeout( ... )

, чтобы помочь автоматизировать это, вы можете использовать оболочку, которая связывает вызовы тайм-аута со строкой (то есть идентификатором div или чем угодно), так что, если есть предыдущий settimeout с той же самой «строкой», он очищает его для Вы автоматически перед установкой снова,

Вы бы использовали массив (то есть словарь / hashmap), чтобы связать строки с дескрипторами.

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 )
}

Конечно, есть и другие способы сделать это ..

2 голосов
/ 25 ноября 2008

Я не проверял ничего из этого, а просто вырезал это в редакторе здесь. Возможно, сработает, может, нет, надеюсь, будет пищей для размышлений.

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 ); 

Последовательные вызовы с одним и тем же идентификатором отменят предыдущий вызов.

2 голосов
/ 24 ноября 2008

Я бы сделал это так:

// 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"]); 
1 голос
/ 10 июня 2011

Вы можете избежать глобальной или меньшей переменной, используя свойство в функции. Это хорошо работает, если функция используется только для этого конкретного контекста.

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 )
}
1 голос
/ 24 ноября 2008

Вы можете хранить несколько флагов в таблице соответствия (хэш), используя objID в качестве ключа.

var moving = {};

function mouseClick()
{
  var objID = "div_0001";
  if (!moving[objID])
  {
    moving[objID] = true;
    moveDiv("div_0001", mouseX, mouseY);
  }
}
0 голосов
/ 20 февраля 2013

Я использую это для принудительной сборки мусора на всех устаревших ссылках тайм-аута, которые действительно не отставали от выполнения моего скрипта:

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 за очень короткое время, но это действительно помогло!

0 голосов
/ 24 ноября 2008

Вы можете установить глобальный флаг где-нибудь (например, var mouseMoveActive = false;), который сообщает вам, уже участвуете ли вы в вызове, и если нет, начните следующий. Вы устанавливаете флаг непосредственно перед тем, как войти в вызов setTimeout, после проверки, установлен ли он уже. Затем в конце процедуры, вызываемой в setTimeout (), вы можете сбросить флаг.

0 голосов
/ 24 ноября 2008

вы всегда можете перезаписать кнопки, чтобы вернуть 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>
0 голосов
/ 24 ноября 2008
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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...