2013-06-28 5 views
7

(я смотрел на все подобные вопросы/ответы, но ни один из них не решить мою проблему.)JavaScript clearTimeout не работает

Код:

var timeoutHandle; 

function showLoader(show) { 
    if (show) { 
     $('.loader').html('Loading...'); 
     $('.loader').show(); 

     timeoutHandle = setTimeout(function() { 
      if ($('.loader').is(':visible')) { 
       $('.loader').html('Still loading...'); 
      } 
     }, 15000); 
    } 
    else { 
     $('.loader').hide(); 
     clearTimeout(timeoutHandle); 
    } 
} 

Функция AJAX просто вызывает showLoader(true) перед вызовом сервер, а затем showLoader(false) после результата. Я все еще иногда вижу изменение текста с «Загрузка ...» на «Загрузка по-прежнему ...» задолго до 15 секунд, так что поток таймера все еще работает. Что-то не так с кодом выше? Или, может быть проблема с другим кодом ..

редактировать: Я должен добавить, что showLoader(true) можно назвать снова (и снова) до ответа от сервера

+0

Что такое функция, которая вызывает «showLoader»? Могу ли я увидеть этот код? –

ответ

14

Вы должны добавить проверку, чтобы увидеть, если есть уже timeoutHandle перед созданием нового.

попробовать это:

if(timeoutHandle){ 
    clearTimeout(timeoutHandle); 
    timeoutHandle = null; 
} 
timeoutHandle = setTimeout(function() { 
    if ($('.loader').is(':visible')) { 
     $('.loader').html('Still loading...'); 
    } 
}, 15000); 

, а затем в случае еще установить timeoutHandle обнулить после ясно, что как так:

clearTimeout(timeoutHandle); 
timeoutHandle = null; 

Это исключит возможность вас, создавая одновременно таймаут, если showLoader(true) функция вызывается более одного раза.

+7

Нет необходимости проверять. Просто позвоните 'clearTimeout' – Ian

3

Что может случиться, так это то, что вы размещаете несколько вызовов до showLoader, так как это глобальная функция, с которой вы можете получить доступ к ней из любого места, вы, как правило, этого не хотите.

Я хотел бы рассмотреть вопрос об изменении его монады реализации в:

function create_loader(elem) { 
    var handle = null; 

    function show() { 
     elem.html('Loading...'); 
     elem.show(); 

     if (handle !== null) { 
      clearTimeout(handle); // clear the previous one 
     } 
     handle = setTimeout(function() { 
      elem.html('Still loading...'); 
     }, 15000); 
    } 

    return { 
     show: show, 
     clear: function() { 
      elem.hide(); 
      clearTimeout(handle); 
      handle = null; 
     } 
    }; 
} 

Использование:

var loader = create_loader($(".loader")); 
loader.clear(); 
loader.show(); 
loader.show(); // each new call to show will reset the 15s timer 
loader.show(); 
loader.show(); 
loader.clear(); 
// and you can make another one that operates independently of other one 
var another_loader = create_loader($(".anotherLoader")); 

Теперь у вас есть loader объект, который знает о своем собственном состоянии.

+0

Очень информативно, спасибо. Решение Омара более понятно для меня. – user982119

+0

Решение Омара в порядке, мое идет дальше. Я удаляю 'timeoutHandle' из глобальной области и привязываюсь к экземпляру загрузчика. Теперь только «загрузчик» находится в глобальном масштабе и сохраняет свое собственное состояние. – Halcyon

+0

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

1

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

0

Вы не называете clearTimeout (timeoutHandle) затем начинает новый запрос, если timeoutHandle существует