Sleep () dosyasının JavaScript sürümü nedir?


2335

sleepJavaScript'te mühendis olmanın aşağıdaki pausecompişlevden ( buradan alınmıştır ) daha iyi bir yolu var mı ?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

Bu, JavaScript'te Uyku kopyası değil - eylemler arasında gecikme ; Bir fonksiyonun ortasında gerçek bir uyku istiyorum ve bir kod parçası yürütülmeden önce bir gecikme değil.


4
İ sürece devam edecek ve sonunda aynı anda çalışan ve kendi aralarında eşzamanlılık biraz yapacak daha setTimeouts sıraya süre setTimeout kullanmak eğer bir süre ortasında sete var
fmsf

159
Bu korkunç bir çözüm - hiçbir şey yapmadan işlem döngülerini çiğniyor olacaksınız.
17 arasında 26

12
Bir uyku için tek amaç yoklama veya geri arama beklemektir - setInterval ve setTimeout her ikisini de bundan daha iyi yapar.
annakata

1
Muhtemelen JavaScript'te devam geçiş tarzı ile istediğinizi yapabilirsiniz. Bu makaleye
Ognyan Dimitrov

Yanıtlar:


2560

2017-2019 güncellemesi

Bu sorunun sorulduğu 2009 yılından bu yana, JavaScript önemli ölçüde gelişmiştir. Diğer tüm yanıtlar artık kullanılmıyor veya aşırı derecede karmaşık. İşte mevcut en iyi uygulama:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

Budur. await sleep(<duration>).

Veya tek astar olarak:

await new Promise(r => setTimeout(r, 2000));

Bunu not et,

  1. awaityalnızca asyncanahtar kelimeyle öneklenmiş işlevlerde veya bazı ortamlarda (örneğin Chrome DevTools konsolu veya Runkit) komut dosyanızın en üst düzeyinde yürütülebilir.
  2. awaitsadece geçerli asyncişlevi duraklatır

İki yeni JavaScript özelliği bu "uyku" işlevinin yazılmasına yardımcı oldu:

uygunluk

Tuhaf bir nedenden ötürü 7'den eski Düğüm'ü ( kullanım ömrünün sonuna ulaştı ) kullanıyorsanız veya eski tarayıcıları hedefliyorsanız, async/ Babel ( JavaScript + yeni özellikleri sade eski JavaScript'e aktaran bir araç ) ile kullanılabilir. , eklentiyle.awaittransform-async-to-generator


5
Burada harika şeyler. Acaba bu JS "uyku" modunu çağırdıktan sonra modern tarayıcı "aktif" / "etkin değil" durumlarını nasıl etkiler veya bunlarla ilişkilidir? Tarayıcı, genel JS için beklendiği gibi uykuyu engelleyebilir, daha sonra "aktif" hale geldiğinde hatırlamak veya farklı bir davranışı var mı?
Andre Canilho

18
Bunun için mevcut tarayıcı desteği nedir? Bu çözüm, tarayıcıların büyük çoğunluğu veya en azından yaygın olanların tümü tarafından desteklenene kadar önceki çözümlerin "eski" olduğunu düşünmem. Aksine, bu çözümü yaygın bir destek olana kadar ilginç ama kullanılamaz / kullanışsız olarak değerlendiririm.
Alvin Thompson

74
Bu "gerçek uyku" değildir ve soruyu cevaplamaz. Sormuş olan kişi stackoverflow.com/questions/758688/sleep-in-javascript ve sorusu arasında net bir ayrım yaptı . Gerçek uykuda başka hiçbir kod çalıştırılamaz (diğer evrelerde olmadığı sürece). Bu cevap diğer soru için iyidir.
niry

4
@jacroe - transpiler ok işlevlerinin yanı sıra asenkron / bekliyor (
IE'nin

11
@niry JavaScript, tek iş parçacıklı bir dil olan "gerçek" uyku için uygun değildir, çünkü kullanıcı arayüzüyle aynı iş parçacığında çalışır ve yanıt vermeyen web sayfalarına neden olur.
Patrick Roberts

849

( 2016 için güncellenmiş cevaba bakınız )

Bir eylemi gerçekleştirmek, beklemek ve sonra başka bir eylem gerçekleştirmek istemek çok mantıklı. Çok iş parçacıklı dillerde yazmaya alışkınsanız, büyük olasılıkla iş parçacığınız uyanana kadar belirli bir süre için yürütme sağlama fikriniz vardır.

Buradaki sorun, JavaScript'in tek iş parçacığı tabanlı bir model olmasıdır. Belirli bir durumda, tüm motorun birkaç saniye beklemesi güzel olabilir, genel olarak kötü bir uygulamadır. Diyelim ki kendiminkini yazarken işlevlerinizi kullanmak istedim? Metodunu aradığımda, metodlarımın hepsi donacaktı. JavaScript bir şekilde işlevinizin yürütme bağlamını koruyabilirse, bir yerde saklayın, sonra geri getirin ve daha sonra devam edin, sonra uyku olabilir, ancak bu temelde iş parçacığı olacaktır.

Yani başkalarının önerdiklerine oldukça bağlı kaldınız - kodunuzu birden fazla fonksiyona bölmeniz gerekecek.

Sorunuz biraz yanlış bir seçim. İstediğiniz gibi uyumak için bir yol yoktur ve önerdiğiniz çözümü takip etmemelisiniz.


45
Bu doğru bir cevap değil. Javascript'in uyku işlevi yoksa, bunun nedeni yalnızca ECMAScript'in gerektirmediğidir. Javascript tasarımından sorumlu kuruluş tarafından bir tasarım seçimidir. Javascript çalışma süresinin bir sonraki kod satırını çalıştırmadan önce belirli bir süre beklemesi sağlanmış olabilir, ancak seçilmemesi seçilmiştir.
Didier

5
Bir uyku gerçek zamanlı hassasiyetle olmasa da JavaScript'te mükemmel bir şekilde uygulanabilir. Sonuçta olay tabanlı bir sistemdir. Zaman uyumsuz çağrılar tamamlanırsa bir olay tetiklenir. Bir uyku () verildiğinde aynı durumun neden mümkün olmadığının hiçbir nedenini göremiyorum, ardından uyku sona erene kadar tarayıcıya kontrol döndürülür ve arama işlevine kontrol döndürülür. Ve evet, aynı zamanda bazen uykunun, özellikle geliştiriciler, tasarımı o kadar kötü bir şekilde berbat etmeden ÖNCE, zamanınız olmayan tamamen yeniden düzenlemenin yanı sıra SİZİN başka bir yolunuz olmadığı için kullanışlı olduğunu kabul ediyorum
Lawrence

Bu fikri takip eden Hipnotik'i deneyin: coolwanglu.github.io/hypnotic/web/demo.html
Tezcat

4
Javascript'i tek iş parçacıklı olarak adlandırmak bir efsanedir. Teknik olarak doğru olsa da, işlevsel olarak çok iş parçacıklı bir dil gibi davranır. Bir çatalı () simüle etmek son derece kolaydır ve verim () gerçekten uygulanamaz olsa da, kilitlemek / semafor için paylaşılan belleği kullanarak oldukça yaklaşabilirsiniz. Ortalama bir programcı için, onu çok iş parçacıklı olarak kabul etmek mantıklıdır; teknik ad sadece dilin geliştiricileri için önemlidir.
Benubird

8
sleep()JS'de neden mümkün olmadığını ve çoğu zaman bir şeyler yapmanın daha iyi yolları olduğunu kabul ediyorum . Ama yine de motorun her şeyi bir tasarım hatası olarak nasıl bağladığını düşünürdüm; sleep()motorun CPU'yu tıkaması ve uygulamayı manyak gibi dondurması olmadan, dilin belirli bir komut dosyası, sayfa veya işlevle sınırlı bir işlevi olmamasının bir nedeni yoktur . Bu 2015 ve tüm bir web tarayıcısını kilitleyememeniz gerekir while(1). Bunun gibi şeyler için Flash'ımız var.
Beejor

660

JavaScript'te, her işlevi en kısa sürede sona erdirmek için yeniden yazarım. DOM değişikliklerinizi yapabilmesi için tarayıcının tekrar kontrol edilmesini istiyorsunuz.

Ne zaman fonksiyonumun ortasında bir uyku istesem, a setTimeout().

Düzenle

Herhangi bir dilde rezil uyku veya gecikme işlevi çok tartışmalıdır. Bazıları her zaman belirli bir işlevselliği ateşlemek için bir sinyal veya geri arama olması gerektiğini söylerken, diğerleri bazen keyfi bir gecikme anının yararlı olduğunu iddia edecektir. Her birinin kendi ve bir kuralının bu endüstride hiçbir şeyi dikte edemeyeceğini söylüyorum.

Uyku fonksiyonu yazmak basittir ve JavaScript Promises ile daha da kullanılabilir hale gelir:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
Kapanış yolu ile. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
kaos

68
tamam, ya kod bir web sayfasında kullanılmak üzere tasarlanmamışsa ne olacak?
Eugenio Miró

10
@ EugenioMiró, kod bir web sayfasında kullanılmak üzere tasarlanmamışsa, ana bilgisayarın nesne modeline bir uyku yöntemi uygulayın. - Sorunun web sayfalarında çalışan javascript'e maruz kalan DOM'a yönelik olduğunu düşünüyorum.
BrainSlugs83

31
@Nosredna evet, async çağrılarının nasıl yapılacağını anlıyoruz, bu bizim uyumamıza yardımcı olmuyor (). Çağrılarımın belirli bir sıraya göre yapılmasını ve verilerin belirli bir sıraya göre geri alınmasını istiyorum. Ben for döngüsünde 5 seviye derinim. Yürütmeyi BLOK yapmak istiyorum. Gerçek bir uyku yöntemi "tarayıcıyı yavaşlatmaz", uyku eller kontrolü tarayıcıya ve hala engelleme sırasında CPU zamanı isteyen diğer iş parçacıklarına geri döner.
BrainSlugs83

382
bu sorunun cevabı değil.
TMS

303

Yalnızca hata ayıklama / dev için , eğer birisi için yararlıysa bunu gönderirim

İlginç şeyler, Firebug'da (ve muhtemelen diğer js konsollarında), girdikten sonra hiçbir şey olmuyor, sadece belirtilen uyku süresinden sonra (...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

Kullanım örneği:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
Bu bir cevap değil. Biraz daha kısa hariç, söz konusu kodla tamamen aynıdır.
jab

16
Meşgul bekliyor, gerçekten mi? JS'de mi? Saniyeler için mi? Bunu yapan bir web sitesini yakalarsam, engellenir.
mafu

34
@mafu Bu yüzden diyor only for debug/dev... rolleyes
xDaizu

12
Bunu asla yapmayın. Bu, CPU'nun yürüttüğü çekirdeğe% 100 vuracak ve engelleyecektir.
noego

3
Bu, async / await yardımcı olmadığından, bir komut satırı javascript uygulaması içinde yararlıdır ve belki de uyumak için SADECE yoldur.
Wheezil

177

Diğer posterlere katılıyorum, yoğun bir uyku sadece kötü bir fikir.

Ancak, setTimeout yürütmeyi beklemez, zaman aşımı süresi dolduktan sonra değil, zaman aşımı SET'ten hemen sonra işlevin bir sonraki satırını yürütür, böylece bir uyku işleminin gerçekleştireceği görevi gerçekleştirmez.

Bunu yapmanın yolu, fonksiyonunuzu parçalardan önce ve sonra bozmaktır.

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

İşlev adlarınızın hala her bir parçanın ne yaptığını doğru bir şekilde açıkladığından emin olun (funcPart1 ve funcPart2 yerine IE GatherInputThenWait ve CheckInput)

Düzenle

Bu yöntem, zaman aşımından sonra karar verdiğiniz kod satırlarını yürütmeme amacını yerine getirirken, kuyruğa giren başka herhangi bir işlemi yürütmek için kontrolü istemci bilgisayara geri döndürür.

Daha Fazla Düzenleme

Yorumlarda belirtildiği gibi bu kesinlikle bir döngüde ÇALIŞMAZ. Bir döngü içinde çalışmasını sağlamak için bazı süslü (çirkin) hack yapabilirsiniz, ancak genel olarak sadece felaket spagetti kodu yapacak.


12
Evet. Bunun zor olduğu bir döngü veya iç içe bir döngü olduğunda. Döngüler için terk etmek ve bunun yerine sayaçları var.
Nosredna

Touché. Demek istediğim, yine de mümkün olurdu, ama bu durumda çirkin ve hackish. Bazı statik boolean durum değişkenleri de kullanabilirsiniz, ancak bu da oldukça hackish.
DevinB

2
Bunun için -1. Yine, bu soruya cevap vermiyor. Bu, "Kod yürütme nasıl engellenir" den çok farklı olan "Bir işlev zaman uyumsuz olarak nasıl yürütülür" gibi bir sorunun cevabıdır.
Deepak GM

6
@Nosredna Hayır, bir kapatma kullanırsınız. Örneğin: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }ve for(var X = 0; X < 3;X++) { foo(X); }- değeri X geçirilir foodaha sonra adı altında tekrar alır ki, indexne zaman foo_continuesonunda adlandırılır.
İzkata

2
@Alexander Elbette öyle, çünkü setTimeout () yöntemi, kodu asenkron olarak çalıştırarak tarayıcının kilitlenmesini önlemektir. console.log()İçini foo_continue()setTimeout sürümüne koyun ve aynı sonucu elde edin.
Mart'ta Izkata

132

$ DEITY aşkı için lütfen meşgul bekleme uyku fonksiyonu yapmayın. setTimeoutve setIntervalihtiyacınız olan her şeyi yapın.

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

Her iki saniyelik aralıkta bir saniye boyunca metni gizleyin. Bu, metni her saniye göstermek ve gizlemek için setInterval ve setTimeout öğelerinin nasıl kullanılacağını gösterir.


3
Pekala her şey değil: setInterval, yoklamadan çok daha iyi bir izlenim bırakıyor.
annakata

3
O kod parçasının ne olacağını değil JavaScript motoru geri tutun?
Deniz Doğan

10
Uykunun senkronize olması gerekmedikçe, bu durumda bu tamamen geçerli bir sorudur.
Aaron Dufour

36
Sanırım çoğumuz JavaScript'in sadece tarayıcı dili olmadığını unutuyor olabiliriz. Bu ahbap setTimeout ile gelen tüm değişken kapsam sorunları ile uğraşmak zorunda kalmadan kısa bir duraklama gerektiren bir Düğüm komut satırı yardımcı programı oluşturabilir.
Phil LaNasa

3
@PhilLaNasa: Eğer sözdizimsel kapanma hala korkutuyorsa, birinin ciddiye alması ve Düğüm 101'den geçmesi gerekiyor.
kaos

113

Bu eski bir soru biraz biliyorum, ama (benim gibi) Rhino ile Javascript kullanıyorsanız, kullanabilirsiniz ...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

4
Bu bir Java çağrısı mı?
Ken Sharp

14
Bu Java değil Javascript
RousseauAlexandre

18
@RousseauAlexandre Yanlış. Öyle JavaScript (zamanda, eşit Nashorn bugünlerde olabilir) Rhino kullanarak
mjaggard

71

JQuery kullanıyorsanız, birisi setTimeout için bir sarıcıdan başka bir şey olmayan bir "gecikme" eklentisi oluşturdu:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

Ardından, beklendiği gibi bir işlev çağrıları satırında kullanabilirsiniz:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
Bu kötü bir çözüm değil. Bağlam ve zincirlenebilirliği korur.
Nosredna

39
JQuery 1.4 itibariyle, jQuery'nin bir .delay()parçasıdır (yukarıdaki uygulamadan farklı anlambilime sahip olsa da). api.jquery.com/delay
Matt Ball

7
Bu sorunun kesinlikle eksik olduğu bir jQuery cevabı idi . Çok memnun oldum!
xDaizu

1
İki bağımsız görüşme arasında bir gecikmeye ihtiyacınız varsa, evet. Bir döngüyü yavaşlatmak için gecikmelere ihtiyacınız varsa, hayır.
WGroleau

46

Ben de uyku çözümü aradım (üretim kodu için değil, sadece dev / testler için) ve bu makaleyi buldum:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... ve işte istemci tarafı çözümlerle başka bir bağlantı: http://www.devcheater.com/

Ayrıca, arama alert()yaparken, uyarı gösterilirken kodunuz da duraklatılır - uyarıyı görüntülememenin ancak aynı etkiyi elde etmenin bir yolunu bulmanız gerekir. :)


35
Katılıyorum, birçok insan "Hayır, bunu üretim kodunda yapma!" Evet, um, istemiyorum. Bunu deneme testi kodunda yapmak istiyorum ve sonuç olarak zarif bir çözüm yapmak için çok fazla zaman harcamak istemiyorum.
user435779

31

Eşzamanlı bir XMLHttpRequest kullanan basit bir çözüm:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

sleep.php içeriği:

<?php sleep($_GET['n']);

Şimdi şöyle çağır: uyku (5);


5
@lukad, setTimeout()Bu işe yararsa kullanın , ancak bunu yapmak 1000 satır geri çağrıyı çözmek anlamına geliyorsa, bu bir şaka gibi görünmeyebilir.
pguardiario

11
Benzersiz yaklaşım, maalesef zaman uyumsuz olmayan XMLHttpRequest'ler kullanımdan kaldırılmıştır ve gelecekte kaldırılacaktır. Bu komik, çünkü bu gerçek beni ilk başta bu soruya yönlendirdi.
Beejor

Bu aslında oldukça iyi bir fikir IMO. Her ne kadar ben uyku API (İstek URL) kötüye kullanılabilir gibi kamu gerektiğini düşünmüyorum.
Vahid Amiri

@Beejor her zaman sadece geleceği düşünmek fütüristik gerçekdışı yaşamak anlamına gelir :-)
user1742529

güzel ama zaman zaman internet yavaş veya Web sitesi ping süresi yüksek argüman zamandan daha fazla komut dosyası uyku olup olmadığını biliyor musunuz. Eğer kullanırsanız gibi sleep(300)450ms için uyku olacaktır javascript kodu daha yanıt için web sitesi almak süresi 150 ms ve. ve internet bağlantısı tarayıcı tarafından kaybedilirse sadece 0 ms çalışır. Yani daha iyi bir çözüm değil
H Chauhan

30

Hadi bakalım. Kodun dediği gibi, kötü bir geliştirici olmayın ve bunu web sitelerinde kullanın. Bu bir geliştirme programı işlevidir.

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

17
Temelde OP ile aynı şeydi.
Andrew Barber

5
Daha kesin olmak gerekirse, OP bir ALTERNATİF istedi.
WGroleau

Çözüm iyi değil, ancak bazı yerlerde async/awaitne yazık ki duyarlı değil ve bunu zorunlu olarak kullanmalıyız.
Nabi KAZ

21

Ben şahsen basit gibi:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

sonra:

sleep(2); // Sleeps for 2 seconds

P5js'de komut dosyaları oluştururken her zaman sahte yükleme süresi oluşturmak için kullanıyorum


3
Bunu ana sorunun en optimize edilmiş versiyonu olarak görüyorum: döngü içinde herhangi bir matematik yapmıyor, sadece düz bir karşılaştırma. Tho okumak biraz zor.
hegez

4
ASLA ASLA YAPMAYIN. Bu işlev çalışırken CPU kullanımını kontrol ettiniz mi? Yeterli zaman ayırırsanız% 100'e yakın olmalıdır.
noego

2
@hegez: Döngü, ne olursa olsun sabit bir duvar saati için çalışacağı göz önüne alındığında, döngüyü optimize etmek noktanın yanında bir şey gibi görünüyor.
ShadowRanger

@noego Nasıl yani? Düğüm 10'da test ettim, hiç CPU kullanım değişikliğim yok
melMass

@melMass Bu işlev, CPU'yu% 100 meşgul tutarak Düğüm iş parçacığını n saniye boyunca engeller. Bu "çözüm" bu iki nedenden dolayı son derece kötü bir fikirdir (bloke + CPU katili). Bekleme engellememeli, dolayısıyla asenkron olmalıdır.
Jeremy Thille

20

İlk:

Aşağıdaki gibi yürütmek istediğiniz bir işlevi tanımlayın:

function alertWorld(){
  alert("Hello World");
}

Ardından setTimeout yöntemiyle yürütülmesini zamanlayın:

setTimeout(alertWorld,1000)

İki şeye dikkat edin

  • ikinci argüman milisaniye cinsinden zamandır
  • ilk argüman olarak parantez olmadan yalnızca işlevin adını (başvuru) iletmeniz gerekir.


18

Çoğu insanın istediği gibi görünmesi için daha iyi bir çözüm anonim bir işlev kullanmaktır:

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

Bu muhtemelen istediğinizi yapan bir şeye en yakın olanıdır.

Birden fazla uykuya ihtiyacınız varsa, bu aceleyle çirkinleşebilir ve aslında tasarımınızı yeniden düşünmeniz gerekebilir.


masaüstü tarayıcılarda ve eski bir cep telefonunda benim için çalışan bu. Denediğim diğerleri işe yaramadı.
Mike

10

Tarayıcılar için, setTimeout ve setInterval öğelerinin gidilecek yol olduğunu kabul ediyorum.

Ancak sunucu tarafı kodu için, bir engelleme işlevi gerektirebilir (örneğin, iş parçacığı eşitlemesini etkili bir şekilde yapabilirsiniz).

Node.js ve meteor kullanıyorsanız, setTimeout'u bir fiberde kullanma sınırlamalarıyla karşılaşmış olabilirsiniz. İşte sunucu tarafı uyku kodu.

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

Bkz. Https://github.com/laverdet/node-fibers#sleep


Server may require a blocking function...
Düğüm'ün

10

Diğer eşzamansız görevlerle kod tutarlılığı için bir Promise setTimeOut kapsüllemek istiyorsunuz: Demo Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {        
        setTimeout(function() { resolve(); }, ms);        
    }));    
}

Bunun gibi kullanılır:

sleep(2000).then(function() { 
   // Do something
});

Promises kullanıyorsanız sözdizimini hatırlamak kolaydır.


4
Bu neden setTimeout (function () {/ * bir şey yap * /}, 2000) kullanmaktan daha iyi?
JSideris

10

2019 Atomics.wait kullanarak güncelleme

9.3 veya daha yüksek Düğümde çalışmalıdır.

Node.js'de oldukça doğru bir zamanlayıcıya ihtiyacım vardı ve bunun için harika çalışıyor. Ancak tarayıcılarda son derece sınırlı bir destek var gibi görünüyor.

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

Birkaç 10 saniyelik zamanlayıcı ölçütleri koştu.

SetTimeout ile 7000 mikrosaniyeye kadar bir hata alıyorum. (7ms)

Atomik ile hatam 600 mikrosaniyenin altında kalıyor gibi görünüyor. (0.6ms)

2020 Güncellemesi: Özetle

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

biri bir sunucu tarafı sayfası, örneğin sleep.jsp, bakışlar ister

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

Bence, arayanda asenkron / beklemeden basit bir işlev olarak uygulanamayan kabul edilen çözümden daha iyi.
GroovyDotCom

Evet, bunun engellendiğini ve bunun genellikle iyi bir şey olmadığını
bildiğiniz sürece

Oldukça güzel, ancak bunun yalnızca Chrome ve Firefox'ta gerçekten desteklendiği gerçeği , web'deki kullanımlar için çok uygun hale getirmiyor. (Kasım 2019)
JGreatorex

9

Buradaki cevapların çoğu yanlış yönlendirilmiş veya en azından modası geçmiş. Javascript'in tek iş parçacıklı olması için hiçbir neden yoktur ve aslında değildir. Bugün, tüm ana tarayıcılar çalışanları destekliyor, bu durum Rhino ve Node.js gibi diğer javascript çalışma zamanlarını çoklu okuma özelliğini destekliyordu.

'Javascript tek iş parçacıklı' geçerli bir cevap değil. Örneğin, bir çalışan içinde uyku işlevinin çalıştırılması, ui iş parçacığında çalışan kodların hiçbirini engellemez.

Jeneratörleri ve verimi destekleyen daha yeni çalışma zamanlarında, tek bir iş parçacıklı ortamda uyku işlevine benzer işlevler getirilebilir:

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);

Bu uyku taklidi, ipliği engellemediğinden gerçek bir uyku fonksiyonundan farklıdır. Javascript'in geçerli setTimeout fonksiyonunun üstünde şekerdir. Bu işlevsellik türü Task.js'de uygulanmıştır ve bugün Firefox'ta çalışmalıdır.


İşçiler IE'de en azından 10 sürümü ile uygulanmaz. Şu anda çok sayıda kullanıcıyı temsil etmektedir.
Beejor

Doğru ve o zaman bile sleepbirden fazla işçi kullanarak uygulamak pratik değildir . Node.js oluşturucu işlevleri zaten uygulanmışsa ve açıklandığı gibi kullanılabilir. Ana tarayıcılar bugünden itibaren tüm jeneratörleri uygulamamıştır.
Gabriel Ratener

8

Javascript uyku / beklemek üzerinde oldukça birkaç web sayfası aradım / googled ... ve javascript "RUN, DELAY, RUN" ... istiyorsanız çoğu cevap ya da "RUN, RUN (yararsız) şeyler), RUN "veya" RUN, RUN + gecikmeli RUN "....

Bu yüzden bazı hamburger yedim ve düşünmeye başladım ::: İşte işe yarayan bir çözüm ... ama koşu kodlarınızı kesmelisiniz ... ::: evet, biliyorum, bu yeniden okunması daha kolay .. hala ...

//......................................... //örnek 1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

// .................................... // örnek2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

// ................. örnek3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

// .............. örnek4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>

5
Tamam, bu setTimeput ile çalışıyor, ama ne olduğunu görmek zor. SetTimeout'un kendisini kullanmak bundan daha kolaydır.
naugtur

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

Gerçek soru ile aynı. Gerçek bir cevap yapmanın pek bir anlamı yok.
EML

2
İyi bir çözüm değil - bunu Selenium'un JavaScriptExecutor'unda kullanmak, Chrome tarayıcımı% 50 oranında bir 2104 MacBook Pro'ya asıyor.
zımpara

7

Herhangi bir bağımlılığı olmayan en kısa çözüm:

await new Promise(resolve => setTimeout(resolve, 5000));

IE11'de çalışmaz. Ok işlevi için sözdizimi hatası alıyoruz.
DDphp

@ Java-DK kullanımıawait new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

JavaScript'te böyle bir uyku yapamazsınız, daha doğrusu yapmamalısınız. Bir uyku veya while döngüsü çalıştırmak, kullanıcının tarayıcısının döngü bitene kadar askıda kalmasına neden olur.

Referans verdiğiniz bağlantıda belirtildiği gibi bir zamanlayıcı kullanın.


6

SetTimeout () kullanmak yerine bir sleep () işlevi isteyebileceğiniz bir senaryo, sonuçta yeni bir açılır pencere açılmasıyla sonuçlanacak bir kullanıcı tıklamasına yanıt veren bir işleviniz varsa ve kısa bir süre gerektiren bir işlem başlatmış olmanızdır. görüntülenir. Açık pencereyi bir kapağa taşımak, genellikle tarayıcı tarafından engellendiği anlamına gelir.


6

Eşzamanlı yürütme ile uğraşmak zorunda kalırsanız uyku işlevinin amacını anlayabiliyorum. SetInterval ve setTimeout işlevleri, yürütme sırasını ana programa geri döndüren paralel bir yürütme iş parçacığı oluşturur; bu, belirli bir sonuç için beklemeniz gerekirse etkisizdir. Tabii ki olaylar ve işleyiciler kullanılabilir, ancak bazı durumlarda amaçlanan bu değildir.


6

İki bitimi de ekliyorum. Test amacıyla meşgul beklemeye ihtiyacım vardı. Bu çok iş olurdu gibi kod bölmek istemiyordu, bu yüzden benim için yaptım basit.

for (var i=0;i<1000000;i++){                    
     //waiting
  }

Bunu yaparken herhangi bir olumsuzluk görmüyorum ve bu benim için hile yaptı.


Bu derlenebilir.
Viktor Sehr

Lütfen bu şekilde yapma. Bu, bloke edici bir uyku çağrısıdır, yani kodunuz JS iş parçacığını gizlerken başka hiçbir javascript çalıştırılamaz.
Steve Midgley

5
@SteveMidgley "kodunuz JS iş parçacığı hog ederken [başka] javascript çalıştırmak mümkün" bana tam olarak OP yapmak istediği gibi görünüyor ¯_ (ツ) _ / ¯
drigoangelo

1
Sadece bazı testler yaptım ve boş bir döngü bile tarayıcı ve CPU'yu (sadece JavaScript değil) engelleyecek gibi görünüyor. Ve fordöngülerin kullanımı, maksimum değerine bakılmaksızın ive hatta içine yerleştirilmiş karmaşık matematik koduyla birlikte hemen hemen her zaman yürütülür . Bu nedenle, sadece birkaç milisaniye beklemediğiniz sürece, JS'de zarif bir şekilde uyumanın bir yolu yok gibi görünüyor.
Beejor

1 milyon çok büyük. Benim için yeterince 10k
Vlad

6

Java'nın uyku yöntemi kullanılarak yapılabilir. FF ve IE'de test ettim ve bilgisayarı kilitlemiyor, kaynakları çiğnemiyor veya sonsuz sunucu isabetlerine neden olmuyor. Bana temiz bir çözüm gibi görünüyor.

Öncelikle Java'nın sayfaya yüklenmesi ve yöntemlerinin kullanılabilir olması gerekir. Bunu yapmak için şunu yaptım:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

Ardından, JS'nizde ağrısız bir duraklama istediğinizde yapmanız gereken tek şey:

java.lang.Thread.sleep(xxx)

Burada xxx milisaniye cinsinden zamandır. Benim durumumda (gerekçe olarak), bu çok küçük bir şirkette arka uç siparişi yerine getirmenin bir parçasıydı ve sunucudan yüklenmesi gereken bir fatura yazdırmam gerekiyordu. Faturayı (web sayfası olarak) bir iFrame'e yükleyip iFrame'i yazdırarak yaptım. Tabii ki, yazdırmadan önce sayfanın tamamen yüklenmesini beklemek zorunda kaldım, bu yüzden JS duraklatmak zorunda kaldı. Bunu, fatura sayfasının (iFrame'de) onLoad olayıyla üst sayfadaki gizli form alanını değiştirmesini sağlayarak başardım. Ve faturayı yazdırmak için üst sayfadaki kod şöyle görünüyordu (netlik için kesilen alakasız parçalar):

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

Böylece kullanıcı düğmeye basar, komut dosyası fatura sayfasını yükler, ardından bekler, fatura sayfasının yüklenip bitmediğini görmek için saniyede bir kontrol eder, ardından kullanıcının yazıcıya göndermesi için yazdırma iletişim kutusunu açar. QED.


12
Yazarın ulaşmak istediği basit şeyi düşünürken oldukça korkunç bir ruh gibi görünüyor.
xaralis

2
Bu, kullanımdan kaldırılan Java Uygulamalarına bağlıdır.
Vahid Amiri

6

Cevapların çoğu (doğrudan) soruyu cevaplamıyor ve bu da cevap vermiyor ...

İşte iki sentim (veya işlevlerim):

Eğer daha az aksak fonksiyonlarını istiyorsanız setTimeoutve setInterval, sadece argümanlar sırasını tersine çevirmek ve onlara güzel isimler verdiğini fonksiyonlarda dolayabilirsiniz:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript sürümleri:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

Daha sonra bunları anonim işlevlerle güzelce kullanabilirsiniz:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

Şimdi kolayca "N milisaniye sonra ..." (veya "her N milisaniye sonra ...")


5

Bir döngü tarafından yürütülen bir dizi aramayı boşluk bırakmak istemek için, prototip ile aşağıdaki kod gibi bir şey kullanabilirsiniz. Prototip olmadan, gecikme işlevini setTimeout ile değiştirebilirsiniz.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

5

Node.js kullanıyorsanız, liflere bir göz atabilirsiniz - düğüme yerel bir C uzantısı, biraz çok iş parçacıklı bir simülasyon.

sleepBir lifte yürütmeyi engelleyecek şekilde gerçek yapmanıza izin verir , ancak ana iplik ve diğer liflerde tıkanmaz.

İşte kendi beniokularından bir örnek:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

- ve sonuçlar:

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
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.