Sonraki satırı yürütmeden önce 5 saniye bekleyin


313

Aşağıdaki bu işlev istediğim gibi çalışmıyor; JS acemi olmak nedenini anlayamıyorum.

Ben olup olmadığını öğrenmeden 5 saniye beklemek gerek newStateolduğunu -1.

Şu anda, beklemiyor, hemen kontrol ediyor.

function stateChange(newState) {
  setTimeout('', 5000);

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}

Yanıtlar:


323

Kodunuzu, sağladığınız geri arama işlevine koymanız gerekir setTimeout:

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}

Diğer tüm kodlar hemen yürütülür.


4
Temel sorun, bazı durumlarda (özellikle test etme) bunun yetersiz bir şekilde yetersiz olmasıdır. Yavaş bir zaman uyumsuz http isteğini simüle etmek için işlevden dönmeden önce 500 ms boyunca uyumanız gerekiyorsa ne olur ?
A.Grandt

14
"Test" ile birim testleri kastediyorsanız: test çerçevenizde zaman uyumsuz testler yürütmenin bir yolu olmalıdır. Manuel sınamayı kastediyorsanız: Chrome'un Ağ sekmesinde yavaş istekleri simüle etmek için Kısma açılır menüsü bulunur.
Joseph Silber

1
bir krom uzantısı geliştirirsem ve enjekte edilen komut dosyasındaki son değerlendirilen değer bana sonuç vermelidir; ve biraz gecikmeye ihtiyacım var?
mirek

184

Bunu gerçekten yapmamalısınız , zaman aşımının doğru kullanımı OP'nin problemi ve belirli bir süre sonra bir şey çalıştırmak istediğiniz başka bir durum için doğru araçtır. Joseph Silber cevabında bunu iyi gösterdi. Olmayan bazı üretim durumda Ancak, gerçekten bir süre için ana iş parçacığı asmak istiyorum, bunu yapacağız.

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}

Formda yürütme ile:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

Buraya geldim çünkü uzun süren engelleme işlemleri (yani pahalı DOM manipülasyonu) etrafında eşzamansız işlemlerin bir karışımını sıralamak için basit bir test örneği oluşturuyordum ve bu benim simüle edilen engelleme işlemim. Bu işe iyi uyuyor, bu yüzden buraya benzer bir kullanım durumu ile gelen herkes için yayınladığımı düşündüm. Yine de, bir while döngüsünde bir Date () nesnesi oluşturur, bu da yeterince uzun süre çalışırsa GC'yi çok fazla etkileyebilir. Ancak yeterince vurgulayamıyorum, bu sadece test için uygundur, herhangi bir gerçek işlevsellik oluşturmak için Joseph Silber'in cevabına bakmalısınız.


7
Bu, javascript yürütülmesini durdurmaz.
Terry Lin

23
@TerryLin Çalıştırmayı deneyin.
Mikrofon

6
Yani temelde CPU zamanını boşa harcıyorsunuz. Ana işlemcinin diğer görevlere odaklanmasını sağlayan iş parçacığını uyku moduna geçirmediğiniz için bu bir bekleme değil.
Kyordhel

6
@Gzork İş parçacığı uykusu, bekleme işlevini uygulamanın yalnızca bir yoludur ve maalesef istemci tarafı javascript bağlamında mevcut değildir. Ancak, istemcideki diğer eşzamansız görevlerin çalışırken tamamlanacağını düşünüyorsanız, bunu test etmediniz. Ana iş parçacığında kullanmamıza rağmen, bir setTimeout aracılığıyla çağrılsa bile, hala diğer asenkron olayları nasıl kesintiye uğradığını gösteren bir keman hazırladım jsfiddle.net/souv51v3/1 - hatta JSFiddle penceresi tamamlandığında yanıt vermiyor.
Mic

1
Kötü çözüm IMHO - "uyurken" CPU'yu koruyor. Doğru uyku yolu async / beklemek ala bu cevap stackoverflow.com/questions/951021/… veya Etienne's.
David Simic

162

İşte yeni async / await sözdizimini kullanan bir çözüm .

ECMAScript 6 ile sunulan yeni bir özellik olduğundan tarayıcı desteğini kontrol ettiğinizden emin olun .

Fayda fonksiyonu:

const delay = ms => new Promise(res => setTimeout(res, ms));

Kullanımı:

const yourFunction = async () => {
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
};

Bu yaklaşımın avantajı, kodunuzun senkronize kod gibi görünmesini ve davranmasını sağlamasıdır.


ECMAScript 6'ya ihtiyacınız yok: Zaman uyumsuz yüklemeyi yapmak için vaatler kullanıyorsanız ve sadece zincirin bir kısmını uzun süre taklit etmek istiyorsanız, bu wait () işlevini zincire ekleyebilirsiniz.
Dovev Hefetz

2
Bu gerçekten yeni sözdizimi ile en iyi cevap. Yukarıdaki wait () çözümünü kullanma ile ilgili sorunlar yaşadım.
pianoman102


36

Javascript'te sadece 5 saniye duraklatmaya çalışmamalısınız. Bu şekilde çalışmaz. Kod işlevini şu andan itibaren 5 saniye çalışacak şekilde zamanlayabilirsiniz, ancak daha sonra çalıştırmak istediğiniz kodu bir işleve koymanız gerekir; bu işlevden sonra kodunuzun geri kalanı hemen çalışmaya devam eder.

Örneğin:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}

Ancak, böyle bir kodunuz varsa:

stateChange(-1);
console.log("Hello");

console.log()Deyimi hemen çalışır. Zaman aşımı stateChange()fonksiyona gelene kadar beklemez . Javascript uygulamasını önceden belirlenmiş bir süre boyunca duraklatamazsınız.

Bunun yerine, gecikmeleri çalıştırmak istediğiniz kodlar setTimeout()geri arama işlevinin içinde olmalıdır (veya bu işlevden çağrılmalıdır).

Dönerek "duraklatmayı" denediyseniz, temelde Javascript yorumlayıcısını bir süre "asarsınız". Javascript kodunuzu yalnızca tek bir iş parçacığında çalıştırdığından, döngü yaptığınızda başka hiçbir şey çalıştırılamaz (başka hiçbir olay işleyicisi çağrılamaz). Bu nedenle, bazı değişkenlerin değişmesini bekleyen döngü asla işe yaramaz çünkü bu değişkeni değiştirmek için başka bir kod çalıştırılamaz.


31
Javascript uygulamasını önceden belirlenmiş bir süre boyunca duraklatamazsınız . Sana beri, yapmamalıdın demek düşünmek can (Kendini asmaya istiyorsanız):var t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);
Joseph Silber

9
@JosephSilber - Tamam, bunu yapabilirsiniz, ancak pratikte pek çok tarayıcı çalışmayan bir komut dosyasının yanıt vermediğini ve korkunç bir kullanıcı deneyimi olduğunu ve pil ömrü için kötü olduğunu ve bir sayfanın Asılırken ... ve bu kötü olurdu.
jfriend00

12
Tabii ki bu korkunç olurdu ve hiç kimse bunu hiç yapmamalı . Ben sadece içsel "iyi-gerçeklerime" dayanamadım . Afedersiniz.
Joseph Silber

31

Zaman uyumsuz bir işlevdeyseniz , bunu tek bir satırda yapabilirsiniz:

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

Dikkat edin , hedef NodeJS ise bunu kullanmak daha verimli olacaktır (önceden tanımlanmış, promisified setTimeout fonksiyonudur):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec

İki uygulama arasındaki fark nedir?
EAzevedo

1
Şu anda bir fark yok. Ancak bir noktada düğüm daha hızlı / daha güvenli / daha verimli hale getirmeye karar verirse, düğüm js sürümünü önceden kullanacaksınız. Her ne kadar okunabilirliğin çoğu insan için anahtar faktör olması daha olası olsa da, bu durumda ilk yolu daha iyi kullanırsınız.
SHL

Teşekkür ederim. Cevabınız üç gündür karşılaştığım bir sorunu çözdü. Teşekkürler.
EAzevedo

8

Bunu dene:

//the code will execute in 1 3 5 7 9 seconds later
function exec() {
    for(var i=0;i<5;i++) {
        setTimeout(function() {
            console.log(new Date());   //It's you code
        },(i+i+1)*1000);
    }
}

7

Mili saniye içinde beklemek için böyle bir işlev oluşturmanın en iyi yolu, bu işlev bağımsız değişkende sağlanan milisaniye bekleyecektir:

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}


3

Joseph Silber'in cevabına dayanarak, bunu biraz daha genel bir şekilde yapardım.

Sizin fonksiyonunuza sahip olacaksınız (soruya dayanarak bir tane oluşturalım):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}

Ve bir bekleme fonksiyonu olabilir:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}

Sonunda sahip olacaksınız:

wait(5000, videoStopped, newState);

Bu bir çözüm, bekleme işlevinde (sadece foo();yerine foo(arg);) argümanları kullanmak istemem ama bu örnek için.


3

Bu çözüm, React Native'ın yenileme kontrolü belgelerinden gelir :

function wait(timeout) {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}

Bunu OP'nin sorusuna uygulamak için, bu işlevi aşağıdakilerle koordineli olarak kullanabilirsiniz await:

await wait(5000);
if (newState == -1) {
    alert('Done');
}

1

İşlevinizde küçük değişiklikler yaparak gecikme ekleyebilirsiniz (zaman uyumsuz ve beklemede).

const add5SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('5 seconds');
    }, 50000);
  });
}

async function asyncFunctionCall() {

  console.log("stpe-1"); 
  const result = await add5SecondsDelay ();
  console.log("step-2 after 5 seconds delay"); 

}

asyncFunctionCall();

-2

angularjs kullanarak:

$timeout(function(){
if(yourvariable===-1){
doSomeThingAfter5Seconds();
}
},5000)

-2

Yeni Js işlevi oluştur

function sleep(delay) {
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      }

Yürütmeyi geciktirmek istediğinizde işlevi çağırın. Gecikme değeri için int cinsinden milisaniye kullanın.

####Some code
 sleep(1000);
####Next line

3
Bu çok fazla kaynak tüketecek.
awavi

-2

PC oyunlarını kenardan veya IE'den çalıştırmak için kullandım. Ve IE Kenarını 7 saniye sonra kendi kendine kapatır.

Firefox ve Google Chrome, oyunları bu şekilde başlatmak için kullanılamaz.

<html<body>
<a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
<img src="game.jpg" width="100%" height="97%" ></a>
<script>
function waitclose(ms){
 var start = new Date().getTime();var end=start;
 while(end < start + ms) {end = new Date().getTime();}
window.open('', '_self', ''); window.close();
}
</script>
</body></html>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.