2014-05-06 13 views
6

Mam pole wyboru, niż można przełączać niektóre zachowania, jednak jeśli ktoś robi 100 kolejnych kliknięć, nie chcę wysyłać 100 żądań na moją stronę serwera.Jak prawidłowo odrzucać żądania ajaxowe

To co mam w miejsce dotychczas (znaleziono ten fragment kodu):

deBouncer = function($,cf,of, interval){ 
    var debounce = function (func, threshold, execAsap) { 
     var timeout; 
     return function debounced() { 
      var obj = this, args = arguments; 
      function delayed() { 
      if (!execAsap) 
       func.apply(obj, args); 
      timeout = null; 
      } 
      if (timeout) 
      clearTimeout(timeout); 
      else if (execAsap) 
      func.apply(obj, args); 
      timeout = setTimeout(delayed, threshold || interval); 
     } 
    } 
    jQuery.fn[cf] = function(fn){ return fn ? this.bind(of, debounce(fn)) : this.trigger(cf); }; 
    }; 

W moim dokumencie gotowy funkcję:

deBouncer(jQuery,'smartoggle', 'click', 1500); 

Potem sam event:

$(window).smartoggle(function(e){ 
    MyToggleFunction(); 
}); 

Działa to tak, jakbym ustawił 1500 ms na okres rozwijania, więc jeśli klikniesz n razy przy 1500 ms, wyśle ​​tylko t on najpóźniej oznajmia serwerowi.

Istnieje jednak efekt uboczny tego, teraz moje zdarzenie click dla innych rzeczy jest pomieszane. Czy robię coś złego tutaj? Czy istnieje lepszy sposób na odrzucenie?

+0

Zdecydowanie jesteś na ścieżce zapisu. Wiążę to wydarzenie z zaznaczonym pytaniem. To może pozwolić ci uprościć inne kodowanie. –

+0

@JeremyJStarcher czy możesz podać przykład tego, co masz na myśli? –

+0

Będę potrzebował zobaczyć twój znacznik ... lub mogę dać ci wymyślony przykład na podstawie tego, jak to zrobię. –

Odpowiedz

2

Nie jestem pewien, czy istnieje "właściwy" sposób, aby to zrobić.

Mimo, że podkreślenia ma takiego narzędzia, które stworzą debounced wersję swojej funkcji ...

var MyToggleDebounced = _.debounce(MyToggleFunction, 1500); 

następnie użyć MyToggleDebounced w click obsługi.

Link to debounce docs on underscorejs

Spójrz na adnotacjami źródło dla jak oni to robią.

8

Po prostu zrezygnuj z funkcji, która wykonuje rzeczywistą pracę i nie załadowałbym do tego całej biblioteki.

var debouncedSomeFunction = debounce(someFunction, 1500); 
 

 
debouncedSomeFunction(); 
 
debouncedSomeFunction(); 
 
debouncedSomeFunction(); 
 

 
setTimeout(debouncedSomeFunction, 2000); 
 

 

 
function debounce(fn, bufferInterval) { 
 
    var timeout; 
 

 
    return function() { 
 
    clearTimeout(timeout); 
 
    timeout = setTimeout(fn.apply.bind(fn, this, arguments), bufferInterval); 
 
    }; 
 

 
} 
 

 
function someFunction() { 
 
    log('someFunction executed'); 
 
} 
 

 
function log(text) { 
 
    document.body.appendChild(document.createTextNode(text)); 
 
    document.body.appendChild(document.createElement('br')); 
 
}

+0

Wiem, że to jest pseudo-kod, ale jestem naprawdę zdezorientowany tym, co oznacza ostatnia linia z jego samoodniesieniem. Może mógłbyś zaktualizować swoją odpowiedź, pokazując prostą implementację * yourFunction *? Próbowałem tego kodu i nie mogłem go uruchomić. – geoidesic

+0

Dla jasności, na wypadek, gdyby ktoś inny był zdezorientowany ostatnim wierszem ... powinien być * var yourFunction = function() {}; yourFunction = debounce (yourFunction, 1500); – geoidesic

+0

@geoidesic Zmodyfikowałem kod, mam nadzieję, że jest to łatwiejsze do zrozumienia. – plalx

0

Myślę, że to pytanie jest lepiej niż się wydaje w pierwszej kolejności. Istnieje pewne zastrzeżenie dotyczące sposobu działania żądań Ajax HTTP. Jeśli ustawisz opóźnienie na 1500ms i będziesz mógł zagwarantować, że każde żądanie zostanie dostarczone w tym czasie, inne odpowiedzi będą działały dobrze. Jeśli jednak jakakolwiek prośba znacznie zwolni, żądania mogą się nie udać. Jeśli tak się stanie, ostatnim przetworzonym żądaniem jest ten, dla którego będą wyświetlane dane, a nie ostatni wysłany.

Napisałem tę klasę, aby uniknąć tego zastrzeżenie (w maszynopisie, ale powinieneś być w stanie go odczytać):

export class AjaxSync { 

    private isLoading: boolean = false; 
    private pendingCallback: Function; 
    private timeout; 

    public debounce(time: number, callback: Function): Function { 
    return this.wrapInTimeout(
     time, 
    () => { 
     if (this.isLoading) { 
      this.pendingCallback = callback; 
      return; 
     } 
     this.isLoading = true; 
     callback() 
      .then(() => { 
      this.isLoading = false; 
      if (this.pendingCallback) { 
       const pendingCallback = this.pendingCallback; 
       this.pendingCallback = null; 
       this.debounce(time, pendingCallback); 
      } 
      }); 
     } 
    ); 
    } 

    private wrapInTimeout(time, callback) { 
    return() => { 
     clearTimeout(this.timeout); 
     this.timeout = setTimeout(callback, time); 
    }; 
    } 
} 

Zapobiegnie to dwa Ajax żądania zrealizowane w tym samym czasie i to wyśle ​​kolejny Żądaj, jeśli jest oczekująca.

Powiązane problemy