Подтвердить что ты не робот

Как вы обрабатываете несколько экземпляров setTimeout()?

Каков наиболее рекомендуемый/лучший способ остановить создание нескольких экземпляров функции setTimeout (в javascript)?

Пример (код psuedo):

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().

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

Я надеюсь, что это ясно...

4b9b3361

Ответ 1

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

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

clearTimeout( handle )

то

handle = setTimeout( ... )

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

Вы должны использовать массив (например, словарь /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

Я бы сделал это следующим образом:

// 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"]); 

Ответ 3

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

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

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

Ответ 4

Можно хранить несколько флагов в таблице поиска (хэш) с помощью objID в качестве ключа.

var moving = {};

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

вы всегда можете перезаписать кнопки 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>

Ответ 8

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

Ответ 9

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

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