2013-06-28 12 views
7

(szukałem w ogóle podobne pytania/odpowiedzi, ale żaden z nich nie rozwiązuje mojego problemu.)JavaScript clearTimeout nie działa

kodu:

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

Funkcja AJAX po prostu wywołuje showLoader(true) przed wywołaniem serwer, a następnie showLoader(false) po wyniku. Ciągle widzę, że tekst zmienia się z "Ładowanie ..." na "Wciąż ładuję ..." na długo przed 15 sekundami, więc wygląda tak, jakby wątek z timerem wciąż działał. Czy coś jest nie tak z powyższym kodem? Lub może być problem z innym kodem ..

edit: muszę dodać, że showLoader(true) można ponownie wywoływany (i znowu) przed odpowiedź od serwera

+0

Jaka jest funkcja, która nazywa "showLoader"? Czy widzę ten kod? –

Odpowiedz

14

Należy dodać sprawdzanie, czy nie jest już timeoutHandle przed utworzeniem nowego.

spróbuj tego:

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

a następnie w przypadku innego ustawienia timeoutHandle null po jasne, że tak:

clearTimeout(timeoutHandle); 
timeoutHandle = null; 

To wyeliminuje szansę na tworzenie jednoczesnych timeoutów jeśli showLoader(true) funkcja jest wywoływana więcej niż jeden raz.

+7

Nie trzeba sprawdzać. Po prostu zadzwoń "clearTimeout" – Ian

3

To, co może się zdarzyć, polega na tym, że umieszczasz wiele połączeń pod numerem showLoader, ponieważ jest to funkcja globalna, z której możesz uzyskać do niej dostęp z dowolnego miejsca. Zazwyczaj nie chcesz tego.

chciałbym rozważyć zmianę go do monada realizacji:

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

Zastosowanie:

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

Teraz masz loader obiektu, który wie o jego własnym państwie.

+0

Bardzo pouczające, dziękuję. Jednak rozwiązanie Omara jest dla mnie bardziej zrozumiałe. – user982119

+0

Rozwiązanie Omara jest w porządku, moje idzie o krok dalej. Usuwam 'timeoutHandle' z globalnego zasięgu i przywiązuję do instancji programu ładującego. Teraz 'loader' znajduje się w zasięgu globalnym i zachowuje swój własny stan. – Halcyon

+0

+1 do enkapsulacji identyfikatora czasomierza. Można wykonać ten krok dalej i dodać wywołanie zwrotne, gdy obciążenie się zakończy. –

1

W swoim wpisie wspominasz, że program ładujący można wywołać wiele razy przed pierwszym zwrotem. To jest twój problem. Nadpisujesz już istniejący timeoutHandle nowym, nie niszcząc już istniejącego uchwytu. Powinieneś sprawdzić, czy timeoutHandle jest ustawione, czy nie ustawione przed utworzeniem nowego.

0

Nie mów clearTimeout (timeoutHandle) następnie rozpoczynając nowy wniosek, jeśli timeoutHandle istnieć

Powiązane problemy