2010-11-10 7 views
8

Mam dość długą działającą (3 do 10 sekund) funkcję, która ładuje dane w tle dla dość rzadko używanych części strony. Mam pytanie, jaki jest optymalny czas działania na wykonanie i czas opóźnienia, aby upewnić się, że reszta strony pozostaje dość interaktywna, ale ładowanie danych nie jest nadmiernie opóźnione przez zerwanie?Ile należy podzielić długo działającą funkcję dla interfejsu użytkownika?

Na przykład:

var i = 0; 
var chunkSize = 10; 
var timeout = 1; 
var data; //some array 

var bigFunction = function() { 
    var nextStop = chunkSize + i; //find next stop 
    if (nextStop > data.length) { nextStop = data.length } 

    for (; i < nextStop; i++) { 
     doSomethingWithData(data[i]); 
    } 
    if (i == data.length) { setTimeout(finalizingFunction, timeout); } 
    else { setTimeout(bigFunction , timeoutLengthInMs); }  
}; 

bigFunction(); //start it all off 

Teraz zrobiłem kilka testów, a chunkSize że daje czas 100ms o wykonanie i 1ms timeout wydawać uzyskując dość czułe UI, ale niektóre przykłady I” Widziane z góry zalecają znacznie większe porcje (~ 300ms) i dłuższe limity czasu (20 do 100 ms). Czy brakuje mi pewnych niebezpieczeństw w przecinaniu mojej funkcji w zbyt wiele małych kawałków, czy też próba i błąd to bezpieczny sposób na określenie tych liczb?

+1

Zdajesz sobie sprawę, że będąc JavaScript (po stronie klienta), procesora, pamięci, połączenie sieciowe itp. czynników maszyny w znacznym stopniu. –

+1

@Jason McCreary, oczywiście. Właśnie dlatego zadaję to pytanie i nie zakładam, że moja metoda prób i błędów w ustalaniu tych liczb jest bezpieczna. – jball

Odpowiedz

3

Każda wartość limitu czasu krótsza niż około 15 ms jest równoważna - przeglądarka zaktualizuje DOM, itd., A następnie uruchomi limit czasu. Aby uzyskać więcej informacji, zobacz this i this. Mam tendencję do używania setTimeout(fn, 0).

chciałbym sprawdzić czas, jaki upłynął zamiast liczb typowania, bo jak Jason zauważył, nie będzie różnic prędkości pomiędzy klientami:

var data; // some array 
var i = 0; 
var MAX_ITERS = 20; // in case the system time gets set backwards, etc 
var CHECK_TIME_EVERY_N_ITERS = 3; // so that we don't check elapsed time excessively 
var TIMEOUT_EVERY_X_MS = 300; 

var bigFunction = function() { 
    var maxI = i + MAX_ITERS; 
    if (maxI > data.length) { maxI = data.length } 

    var nextTimeI; 
    var startTime = (new Date()).getTime(); // ms since 1970 
    var msElapsed; 

    while (i < maxI) { 
     nextTimeI = i + CHECK_TIME_EVERY_N_ITERS; 
     if (nextTimeI > data.length) { nextTimeI = data.length } 

     for (; i < nextTimeI; i++) { 
      doSomethingWithData(data[i]); 
     } 

     msElapsed = (new Date()).getTime() - startTime; 
     if (msElapsed > TIMEOUT_EVERY_X_MS) { 
      break; 
     } 
    } 

    if (i == data.length) { 
     setTimeout(finalizingFunction, 0); 
    } else { 
     setTimeout(bigFunction , 0); 
    } 
}; 

bigFunction(); //start it all off 
+0

Podoba mi się pomysł na to, aby dopasować go do rzeczywistego klienta, choć myślę, że po prostu użyj pierwszego uruchomienia, aby uzyskać przybliżoną średnią czasu na iterację, a następnie ustaw wszystkie kolejne przebiegi na podstawie rozsądnej liczby. – jball

0

Limit czasu 1ms nie jest tak naprawdę 1 ms. Do czasu, gdy wątek się wyda, aby osiągnąć 1 ms, prawdopodobnie dał znacznie więcej - ponieważ typowy przedział czasu wątku wynosi 30 ms. Dowolna liczba innych wątków mogła zostać wykonana podczas timeoutu 1ms, co może oznaczać, że upłynęło 200 ms, zanim ponownie uzyskasz kontrolę.

Dlaczego po prostu nie wykonać "doSomethingWithData" w zupełnie innym wątku?

+1

To jest javascript: istnieje tylko jeden wątek. Przynajmniej w przypadku przeglądarek istnieje tylko jeden wątek. –

+0

Do czasu, gdy pracownicy sieciowi są często (90 +% przeglądarek), nie liczę na posiadanie więcej niż jednego wątku do wykonania mojego javascriptu. – jball

Powiązane problemy