Как вы обрабатываете несколько экземпляров 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().
Опция, которую я видел, - создать флаг, который позволяет только вызывать таймаут, если другой экземпляр недоступен... это лучший способ пойти?
Я надеюсь, что это ясно...
Ответы
Ответ 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+ за очень короткое время, но это действительно трюк!