Jak ustawić opóźnienie czasowe w javascript

170

Mam ten kawałek js w mojej witrynie, aby przełączać obrazy, ale potrzebuję opóźnienia po kliknięciu obrazu po raz drugi. Opóźnienie powinno wynosić 1000 ms. Więc należy kliknąć img.jpg, a następnie pojawi się img_onclick.jpg. Następnie kliknij obraz img_onclick.jpg. Następnie powinno nastąpić opóźnienie 1000 ms, zanim img.jpg zostanie ponownie wyświetlony.

Oto kod:

jQuery(document).ready(function($) {

    $(".toggle-container").hide();
    $(".trigger").toggle(function () {
        $(this).addClass("active");
        $(".trigger").find('img').prop('src', 'http://localhost:8888/images/img_onclick.jpg');
    }, function () {
        $(this).removeClass("active");
        $(".trigger").find('img').prop('src', 'http://localhost:8888/images/img.jpg');
    });
    $(".trigger").click(function () {
        $(this).next(".toggle-container").slideToggle();
    });
});
Niebiesko-pomarańczowy
źródło
8
setTimeout(function(){/*YourCode*/},1000);
marteljn
prawdopodobnie szukasz .stop()chociaż. Zajrzyj tutaj api.jquery.com/stop
Mark Walters
Możliwy duplikat Put a Delay in Javascript
Anonymous

Odpowiedzi:

380

Zastosowanie setTimeout():

var delayInMilliseconds = 1000; //1 second

setTimeout(function() {
  //your code to be executed after 1 second
}, delayInMilliseconds);

Jeśli chcesz to zrobić bez setTimeout: Odnieś się do tego pytania .

HIRA THAKUR
źródło
6
jak to zrobić synchronicznie? kod wewnątrz setTimeout nie rozpoznaje właściwości klas.
ishandutta2007
@ ishandutta2007 zobacz moją odpowiedź poniżej -> stackoverflow.com/a/49813472/3919057
Ninjaneer
50
setTimeout(function(){


}, 500); 

Umieść swój kod wewnątrz { }

500 = 0,5 sekundy

2200 = 2,2 sekundy

itp.

maudulus
źródło
18

Rozwiązanie ES-6

Poniżej znajduje się przykładowy kod, który używa aync / await, aby mieć rzeczywiste opóźnienie.

Istnieje wiele ograniczeń i może to nie być przydatne, ale po prostu publikuj tutaj dla zabawy.

    async function delay(delayInms) {
      return new Promise(resolve  => {
        setTimeout(() => {
          resolve(2);
        }, delayInms);
      });
    }
    async function sample() {
      console.log('a');
      console.log('waiting...')
      let delayres = await delay(3000);
      console.log('b');
    }
    sample();

Ninjaneer
źródło
3
To nie jest konieczne dla delayfunkcji, aby być asynchroniczny. To niesamowite opóźnienie działa, gdy w treści funkcji asynchronicznej oczekuje się Obietnicy zwracanej przez zwykłą funkcję.
Intervoice
13

Istnieją dwa (najczęściej używane) typy funkcji timera w javascript setTimeouti setInterval( inne )

Obie te metody mają ten sam podpis. Jako parametr przyjmują funkcję oddzwaniania i czas opóźnienia.

setTimeoutwykonuje tylko raz po opóźnieniu, podczas gdy setIntervalwywołuje funkcję zwrotną po każdych milisekach opóźnienia.

obie te metody zwracają identyfikator w postaci liczby całkowitej, którego można użyć do wyczyszczenia ich przed upływem czasu.

clearTimeouti clearIntervalobie te metody pobierają identyfikator całkowity zwrócony z powyższych funkcji setTimeoutisetInterval

Przykład:

setTimeout

alert("before setTimeout");

setTimeout(function(){
        alert("I am setTimeout");
   },1000); //delay is in milliseconds 

  alert("after setTimeout");

Jeśli uruchomisz powyższy kod, zobaczysz, że ostrzega, before setTimeouta następnie after setTimeoutostrzega I am setTimeoutpo 1 sek. (1000 ms)

Z przykładu można zauważyć, że setTimeout(...)jest asynchroniczny, co oznacza, że ​​nie czeka na upłynięcie licznika czasu przed przejściem do następnej instrukcji, tj.alert("after setTimeout");

Przykład:

setInterval

alert("before setInterval"); //called first

 var tid = setInterval(function(){
        //called 5 times each time after one second  
      //before getting cleared by below timeout. 
        alert("I am setInterval");
   },1000); //delay is in milliseconds 

  alert("after setInterval"); //called second

setTimeout(function(){
     clearInterval(tid); //clear above interval after 5 seconds
},5000);

Jeśli uruchomisz powyższy kod, zobaczysz, że ostrzega, before setIntervala następnie after setIntervalostrzega I am setInterval 5 razy po 1 sek. (1000 ms), ponieważ setTimeout czyści licznik czasu po 5 sekundach lub co 1 sekundę otrzymasz alert I am setIntervalNieskończenie.

Jak przeglądarka to robi wewnętrznie?

Krótko wyjaśnię.

Aby zrozumieć, że musisz wiedzieć o kolejce zdarzeń w javascript. W przeglądarce zaimplementowano kolejkę zdarzeń. Za każdym razem, gdy zdarzenie zostanie wyzwolone w js, wszystkie te zdarzenia (takie jak kliknięcie itp.) Są dodawane do tej kolejki. Kiedy Twoja przeglądarka nie ma nic do wykonania, pobiera zdarzenie z kolejki i wykonuje je jedno po drugim.

Teraz, gdy zadzwonisz setTimeoutlub setIntervaltwój callback zostanie zarejestrowany do licznika czasu w przeglądarce, zostanie on dodany do kolejki zdarzeń po upływie określonego czasu i ostatecznie javascript pobierze zdarzenie z kolejki i wykonuje je.

Dzieje się tak, ponieważ silnik javascript jest jednowątkowy i może wykonywać tylko jedną rzecz naraz. Dlatego nie mogą wykonywać innych skryptów javascript i śledzić Twojego timera. Dlatego te timery są rejestrowane w przeglądarce (przeglądarka nie jest jednowątkowa) i może śledzić licznik czasu i dodawać zdarzenie do kolejki po jego wygaśnięciu.

to samo dzieje się setIntervaltylko w tym przypadku, gdy zdarzenie jest ponownie dodawane do kolejki po określonym czasie, aż zostanie wyczyszczone lub odświeżona strona przeglądarki.

Uwaga

Parametr opóźnienia przekazany do tych funkcji to minimalny czas opóźnienia wykonania wywołania zwrotnego. Dzieje się tak, ponieważ po wygaśnięciu licznika czasu przeglądarka dodaje zdarzenie do kolejki do wykonania przez silnik javascript, ale wykonanie wywołania zwrotnego zależy od pozycji Twoich zdarzeń w kolejce, a ponieważ silnik jest jednowątkowy, wykona wszystkie zdarzenia w kolejka jeden po drugim.

W związku z tym wywołanie zwrotnego wywołania zwrotnego może czasami zająć więcej niż określony czas opóźnienia, aby zostać wywołanym specjalnie, gdy inny kod blokuje wątek i nie daje czasu na przetworzenie tego, co jest w kolejce.

A jak wspomniałem, javascript to pojedynczy wątek. Tak więc, jeśli długo blokujesz wątek.

Jak ten kod

while(true) { //infinite loop 
}

Twój użytkownik może otrzymać komunikat informujący, że strona nie odpowiada .

Nadir Laskar
źródło
1
Czy możesz mi powiedzieć, jak mogę zatrzymać asynchroniczne zachowanie metody setTimeout ()?
Chandan Purbia
Nie używasz, setTimeoutjeśli nie chcesz zachowania asynchronicznego.
Nadir Laskar
5

W przypadku połączeń synchronizacyjnych możesz użyć poniższej metody:

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
user1188867
źródło
0

Jeśli potrzebujesz odświeżenia, jest to kolejna możliwość:

setTimeout(function () { 
    $("#jsSegurosProductos").jsGrid("refresh"); 
}, 1000);
oOJITOSo
źródło
0

Oto, co robię, aby rozwiązać ten problem. Zgadzam się, że jest to spowodowane problemem z synchronizacją i potrzebowałem przerwy, aby wykonać kod.

var delayInMilliseconds = 1000; 
setTimeout(function() {
 //add your code here to execute
 }, delayInMilliseconds);

Ten nowy kod wstrzyma go na 1 sekundę, a tymczasem uruchomi Twój kod.

Amir Md Amiruzzaman
źródło
0

Przekażę swój wkład, ponieważ pomaga mi to zrozumieć, co robię.

Aby zrobić pokaz slajdów z automatycznym przewijaniem, który ma 3 sekundy oczekiwania, wykonałem następujące czynności:

var isPlaying = true;

function autoPlay(playing){
   var delayTime = 3000;
   var timeIncrement = 3000;

   if(playing){
        for(var i=0; i<6; i++){//I have 6 images
            setTimeout(nextImage, delayTime);
            delayTime += timeIncrement;
        }
        isPlaying = false;

   }else{
       alert("auto play off");
   }
}

autoPlay(isPlaying);

Pamiętaj, że podczas wykonywania setTimeout () w ten sposób; wykona wszystkie funkcje przekroczenia limitu czasu tak, jakby były wykonywane w tym samym czasie, przy założeniu, że w ustawieniu setTimeout (nextImage, delayTime); czas opóźnienia to statyczne 3000 milisekund.

To, co zrobiłem, aby to uwzględnić, to dodanie dodatkowych 3000 mili / s po każdym zwiększeniu pętli przez delayTime += timeIncrement;.

Dla tych, którym zależy na tym, jak wygląda moje nextImage ():

function nextImage(){
    if(currentImg === 1){//change to img 2
        for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[1].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[1];
        imgDescription.innerHTML = imgDescText[1];

        currentImg = 2;
    }
    else if(currentImg === 2){//change to img 3
        for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[2].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[2];
        imgDescription.innerHTML = imgDescText[2];

        currentImg = 3;
    }
    else if(currentImg === 3){//change to img 4
        for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[3].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[3];
        imgDescription.innerHTML = imgDescText[3];

        currentImg = 4;
    }
    else if(currentImg === 4){//change to img 5
        for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[4].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[4];
        imgDescription.innerHTML = imgDescText[4];

        currentImg = 5;
    }
    else if(currentImg === 5){//change to img 6
    for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[5].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[5];
        imgDescription.innerHTML = imgDescText[5];

        currentImg = 6;
    }
    else if(currentImg === 6){//change to img 1
        for(var i=0; i<6; i++){
            images[i].style.zIndex = "0";
        }
        images[0].style.zIndex = "1";
        imgNumber.innerHTML = imageNumber_Text[0];
        imgDescription.innerHTML = imgDescText[0];

        currentImg = 1;
    }
}
noetix
źródło