2015-11-20 3 views
2

У меня есть div, который слушает событие «mouseenter» и запускает библиотечную функцию (которую я не могу редактировать) через 5 секунд (реализован с помощью setTimeout).Как остановить вызов функции Javascript внутри setTimeout после его увольнения?

Однако, если пользователь нажимает на div в течение этих 5 секунд, setTimeout следует отменить, а функция не должна запускаться (реализована с помощью clearTimeout). Щелчок также удалит элемент, на который опирается функция libraryFunction.

В настоящее время у меня есть код ниже:

var timeoutVar; 
$("#mydiv").on("mouseenter", function(event) { 
    timeoutVar = setTimeout(function() { 
     runLibraryFunction(object); 
    }, 5000); 
}); 

$("#mydiv").on("click", function(event) { 
    clearTimeout(timeoutVar); 
    removeObject(object); 
}); 

Это работает по большей части, однако, есть крайний случай, когда DIV нажата только через 5 секунд, и в то время как runLibraryFunction() при выполнении. Поскольку событие «щелчок» удаляет объект, который требуется для функции runLibraryFunction, и это происходит при запуске runLibraryFunction, runLibraryFunction затем выдает ошибку.

Есть ли способ остановить вызов runLibraryFunction() после его увольнения?

+0

Что необходимо удалить объект после нажатия? –

+2

Это похоже на проблему XY. Что вы делаете с удалением 'removeObject()' в конце своей функции 'runLibraryFunction', когда это делается с ней? –

+0

Я бы предположил, что внутри таймаута запускается событие click вместо функции вызова напрямую. Это сделает поток кода немного более чистым. Также после того, как вы нажали, вы можете установить флаг как 'processing' и только в его ложном состоянии, функции вызова. – Rajesh

ответ

1

Можно добавить свойство объекта при запуске функции библиотеки, тем самым защищая его от удаления, как:

var timeoutVar; 
$("#mydiv").on("mouseenter", function(event) { 
    timeoutVar = setTimeout(function() { 
     object.keepmealive=1; 
     runLibraryFunction(object); 
     if (object) delete object.keepmealive; 
    }, 5000); 
}); 

$("#mydiv").on("click", function(event) { 
    clearTimeout(timeoutVar); 
    if (!object.keepmealive) removeObject(object); 
}); 

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

+0

Это сделало трюк, спасибо! – TheZ

2

Tricky, но будет работать

timeoutVar = setTimeout(function() { 
     setTimeout(function(){ 
      if(object) 
      runLibraryFunction(object); 
     },1000); 
    }, 5000); 

Держите же остальное.

или использовать немедленно вызываемые функции

timeoutVar = setTimeout(function() { 
        (function(object){ 
         runLibraryFunction(object); 
        })(object); 
       }, 5000); 

Теперь объект всегда будет доступен

+0

Использование вложенного тайм-аута просто добавит буфер около 1-1,5 сек. Если обработка занимает больше, проблема будет сохраняться. Также есть ли разница между вызывающей функцией напрямую и с использованием IIFE? – Rajesh

+0

Да, конечно, IIFE позволит «объекту» всегда находиться в области «runLibraryFunction» – void

+0

, добавив простое условие, если это не решит его?Я предполагаю, что добавление флага было бы лучшим подходом, чем использование IIFE или вложенных тайм-аутов – Rajesh

0

Я бы отвязать событие во время обработки, и перепривязываю его потом с помощью s рекурсивной функции следующим образом:

var timeoutVar; 
var init = function(){ 
    $("#mydiv").on("mouseenter", function(event) { 
    timeoutVar = setTimeout(function() { 
     $("#mydiv").off() 
     runLibraryFunction(object, function(){ 
      init() 
     }); 
    }, 5000); 
    }); 
}; 

$("#mydiv").on("click", function(event) { 
    clearTimeout(timeoutVar); 
    removeObject(object); 
}); 

init(); 
Смежные вопросы