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


Bir mühendis için daha iyi bir yolu var mı sleep JavaScript’ten aşağıdakilerden pausecomp işlev (buradan alındı)?

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

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


1527
2017-10-07 09:44


Menşei


SetTimeout'u kullanırsam, bir süre ortasına ayarlamak, süre sonunda aynı anda çalışacak ve kendi aralarında biraz eşzamanlılık yapacak olan daha setTimeoutları işlemeye ve sıralamaya devam edecek - fmsf
Bu korkunç bir çözüm - hiçbir şey yapmadan işlem döngülerini çiğniyor olacaksınız. - 17 of 26
Bir uyku için tek amaç yoklama veya bir geri arama beklemektir - setInterval ve setTimeout bundan daha iyisini yapar. - annakata
Muhtemelen JavaScript'de devam eden stil ile istediğinizi yapabilirsiniz. Şuna baksana Bu makale. - Ognyan Dimitrov


Cevaplar:


2017 güncellemesi

Bu sorunun sorulduğu 2009 yılından bu yana, JavaScript önemli ölçüde gelişmiştir. Diğer tüm cevaplar artık eskimiş veya aşırı karmaşıktır. İş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 second later');
}

demo();

Budur. await sleep(<duration>).

Bu kodu canlı olarak deneyebilirsiniz Runkit'te. Bunu not et,

  1. await sadece ön eklenmiş fonksiyonlarda çalıştırılabilir async Anahtar kelime. Runkit, kodunuzu çalıştırmadan önce bir async işlevinde sarar.
  2. await sadece akımı duraklatır async fonksiyon

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

uygunluk

Herhangi bir nedenle, 7'den büyük bir Node kullanıyor veya eski tarayıcıları hedefliyorsanız async/await hala üzerinden kullanılabilir Babil (olacak bir araç transpile JavaScript + yeni özellikleri düz eski JavaScript ile) transform-async-to-generator Eklenti. Koşmak

npm install babel-cli --save

yaratmak .babelrc ile:

{
  "plugins": [
    "transform-async-to-generator",
  ]
}

Sonra kodunuzu

node_modules/babel-cli/bin/babel-node.js sleep.js

Yine de, 7 veya daha üstü bir düğüm kullanıyorsanız veya modern tarayıcıları hedefliyorsanız buna ihtiyacınız yoktur.


1089



Burada harika şeyler. JS'nin "uyku" modunu çağırmasından sonra, bu durum modern tarayıcıları "etkin" / "etkin olmayan" durumlarla nasıl ilişkilendirir veya ilişkilendirir? Tarayıcı, genel JS için beklendiği gibi uykuyu engelleyebilir, daha sonra "aktif" hale geldiğinde hatırlayabilir veya farklı bir davranışa sahip olabilir mi? - Andre Canilho
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 ortak olanları tarafından desteklenene kadar önceki çözümlerin "eski" olduğunu düşünmüyorum. Aksine, bu çözümü, yaygın desteğe sahip olana kadar ilginç ama kullanılamaz / pratik olmayan bir şekilde ele alacağım. - Alvin Thompson
@AlvinThompson: modern web geliştirme çoğunluğu transpilers kullanır, bu nedenle yerel tarayıcı desteği daha temiz ve geleceğe hazır koddan daha az önem taşır. Her neyse, gör kullanabilirmiyim. - Dan Dascalescu
Bu "gerçek uyku" değildir ve soruya cevap vermez. Sorulan kişi aralarında net bir ayrım yaptı stackoverflow.com/questions/758688/sleep-in-javascript ve onun sorusu. Gerçek uykuda başka hiçbir kod yürütülemez (diğer iş parçacığında olmadığı sürece). Bu cevap diğer soru için iyidir. - niry
@jacroe - transpiler ok işlevlerini ve async / await'i (IE'nin kanı yine de kusmasına neden olacak şekilde) idare eder. - Jaromanda X


(Bkz. 2016 için güncellenmiş cevap)

Bir eylemi gerçekleştirmek, beklemek, sonra başka bir eylem yapmak istemek oldukça mantıklı. Çok iş parçacıklı dillerde yazıyorsanız, iş parçacığınız uyanana kadar belirli bir süre için yürütme hakkınız olabilir.

Buradaki sorun, JavaScript'in tek-thread etkinlik tabanlı bir model olmasıdır. Belirli bir durumda, tüm motorun birkaç saniye beklemesi iyi olabilir, genel olarak kötü bir uygulamadır. Kendi yazımı yaparken fonksiyonlarınızı kullanmak istediğimi varsayalım mı? Metodunu aradığımda, yöntemlerim donacaktı. JavaScript bir şekilde işlevinizin yürütme bağlamını koruyabilirse, bir yere depolayın, sonra geri getirin ve daha sonra devam edin, sonra uyku olabilir, ancak bu temel olarak iş parçacığı olacaktır.

Yani, başkalarının önerdiği şeylerle takılıp kaldınız - kodunuzu birden fazla işleve ayırmanız gerekir.

Senin sorunun yanlış bir seçim, o zaman. İstediğiniz şekilde uyumak için hiçbir yol yoktur, önerdiğiniz çözümü izlememelisiniz.


830



Bu doğru bir cevap değil. Javascript'in uyku fonksiyonu yoksa, bunun nedeni sadece ECMAScript'in gerektirmemesidir. Javascript tasarımından sorumlu vücut 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 beklediği, ancak bunun yapılmamasına karar verilmiş olabilir. - Didier A.
Bir uyku, gerçek zamanlı doğrulukla değil, JavaScript'te mükemmel bir şekilde uygulanabilir. Sonuçta olay tabanlı bir sistemdir. Zaman uyumsuz çağrıları tamamlandığında bir olay tetiklenir. Uykunun sona ermesine kadar kontrolün tarayıcıya geri döndürülmesinden sonra bir uyku () verilirken, çağrıyı kontrol etme işlevine geri döndüğünde aynı neden mümkün değildir. Ve evet, bazen uyumak, özellikle geliştiriciler ne zaman o kadar kötü bir şekilde tasarımınızı berbat ettiğinizi bildiğiniz zaman, SİZE hiçbir zamanın olmadığı, tam olarak refactoring dışında başka bir yolunuz olmadığına katılıyorum - Lawrence
Bu fikri takip eden Hipnotik'i deneyin: coolwanglu.github.io/hypnotic/web/demo.html - Tezcat
Tek iş parçacıklı javascript'i aramak bir efsane. Teknik olarak doğru olsa da, işlevsel olarak çok iş parçacıklı bir şerit gibi davranır. Bir çatalı () simüle etmek kolay bir şekilde kolaydır ve verim () gerçekten uygulanamaz olsa da, kilitleme / semafor için paylaşılan belleği kullanarak oldukça yakın olabilirsiniz. Ortalama programcı için, onu çok iş parçacıklı olarak ele almak mantıklıdır; Teknik isim sadece dilin geliştiricileri için önemlidir. - Benubird
Neden katılıyorum sleep() JS'de mümkün değildir ve çoğu zaman işleri yapmak için daha iyi yollar vardır. Ama motorun her şeyi tasarım kusuru olarak nasıl bağladığını hala düşünürdüm; dilin bir nedeni olamazdı. sleep() Belirli bir komut dizisi, sayfa veya işlevsiz bir şekilde motorun clobbering yapıp motoru bir manyak gibi dondurması. 2015 ve tüm web tarayıcısını while(1). Bunun gibi şeyler için Flash'ımız var. - Beejor


JavaScript'te, her işlevi mümkün olan en kısa sürede sona erdirecek şekilde yeniden yazarım. Tarayıcınızı tekrar kontrol etmek istediğinizde DOM'nizi değiştirebilir.

Fonksiyonumun ortasında her zaman uyumak istedim, bir setTimeout().

Bu cevabı düzenleyeceğim çünkü bunu faydalı buldum:

Kötü bir uyku ya da gecikme, herhangi bir dilde işlev görür. Bazıları, belirli bir işlevselliği tetiklemek için her zaman bir sinyal ya da geri çağrı olması gerektiğini söyler, diğerleri bazen keyfi bir gecikme zamanının yararlı olduğunu tartışır. Bunu kendi başına ve bir kuralın bu endüstride hiçbir şeyi dikte edemeyeceğini söylüyorum.

Bir uyku fonksiyonu yazmak basittir ve JavaScript Promises ile daha da kullanışlı hale getirilir:

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

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

590



Kapatma yoluyla. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); } - chaos
tamam, ve kod bir web sayfasında kullanılmak üzere tasarlanmamışsa ne olacak? - Eugenio Miró
@ EugenioMiró kodu bir web sayfasında kullanılmak üzere tasarlanmamışsa, konağın nesne modelinin bir uyku yöntemi uygulamasını sağlayın. - Sanırım soru web sayfalarında çalışan javascript'e maruz kalan DOM'a doğru yönlendiriliyor. - BrainSlugs83
@Nosredna evet, uyumsuz çağrıları nasıl yapacağımızı anlıyoruz, bu bize uyumaya yardımcı olmaz (). Aramalarımın belirli bir sırayla yapılmasını ve verilerin belirli bir sırayla geri alınmasını istiyorum. For döngüsünde 5 seviye derinim. BLOCK yürütmesini istiyorum. Gerçek bir uyku metodu "tarayıcıyı yavaşlatmaz", uyku elleri tarayıcıya ve hala bloke ederken CPU zamanını isteyen diğer tüm konulara geri döner. - BrainSlugs83
Bu sorunun cevabı değildir. - TMS


Sadece hata ayıklama / dev için Birini işe yararsa

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

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 !"); }

269



Bu bir cevap değil. Bu sorudaki kodla tamamen aynı, biraz daha kısa hariç. - jab
Meşgul beklemek, gerçekten mi? JS'de mi? Saniye için? Bunu yapan bir web sitesi yakalarsam engellenir. - mafu
@mafu Bu yüzden diyor only for debug/dev... rolleyes - xDaizu
@mafu bu doğru, muhtemelen kendi sorusunu hak ettiği uygun bir örnekle gelmek çok zor! - xDaizu
ASLA BU ASLA. Bu, CPU'nun çekirdeği üzerinde% 100'e vuracak ve onu engelleyecektir. - noego


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

Ancak, setTimeout yürütmeyi beklemez, zaman aşımı sona erdikten sonra, zaman aşımı süresi bittikten hemen sonra, işlevin bir sonraki satırını yürütür, böylece bir uykunun gerçekleştireceği aynı görevi yerine getiremez.

Bunu yapmanın yolu, işlevinizi parçalara ayırmadan önce ve sonra parçalara ayırmaktı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 her parçanın ne yaptığını hala doğru şekilde belirlediğinden emin olun (funcPart1 ve funcPart2 yerine I.E. GatherInputThenWait ve CheckInput,)

Düzenle 

Bu yöntem, zaman aşımınızdan sonra karar verdiğiniz kod satırlarını yürütmemenizin amacını yerine getirirken, sıraya koyduğu başka herhangi bir işlemi yürütmek için yine de istemci PC'ye geri döndürülür.

Daha fazla düzenleme

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


164



Evet. Bu zorlaştığı yerde, bir döngü veya yuvalanmış bir döngü olduğunda bile. Senin döngüler için terk etmek ve bunun yerine sayaçları var. - Nosredna
Touché. Demek istediğim, bu hala mümkün olabilir, ama bu durumda çirkin ve hackish. Bazı statik boole durum değişkenleri de kullanabilirsiniz, ancak bu aynı zamanda oldukça hackish. - DevinB
Bunun için -1. Yine, bu soruya cevap vermiyor. Bu, "Bir kod yürütme engelleme" bölümünden çok farklı olan "Eşzamansız bir işlev nasıl çalıştırılır" gibi bir sorunun yanıtıdır. - Deepak G M
@Nosredna Hayır, bir kapatma kullanacaksın. Örneğin: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); } ve for(var X = 0; X < 3;X++) { foo(X); } - değer X geçirilir fooDaha sonra adı altında yeniden kullanılır index ne zaman foo_continue sonunda çağrılır. - Izkata
@Alexander Tabii ki, çünkü setTimeout () noktası, tarayıcının kodu asenkron olarak çalıştırarak kilitlemesini engellemektir. Koy console.log()içeride foo_continue() setTimeout sürümünde ve aynı sonucu alırsınız. - Izkata


$ DEITY'nin aşkı için lütfen meşgul-beklemek uyku fonksiyonu yapmayın. setTimeout ve setInterval İhtiyacınız olan her şeyi yapın.


113



Katılıyorum. Gerçek bir "uyku" bütün javascript motorunu dondurmaz mıydı ... - Skurmedel
Tamamen her şey değil: setInterval, oylama konusunda çok daha iyi bir izlenim bırakıyor. - annakata
Bu kod parçası ne olurdu? değil JavaScript motorunda geri çekilsin mi? - Deniz Dogan
Senkronize olmak için uykuya ihtiyacınız olmadıkça, bu tam olarak geçerli bir sorudur. - Aaron Dufour
Bence çoğumuz JavaScript'in sadece tarayıcılara yönelik bir dil olmadığını unutuyor olabiliriz. Bu kişi, setTimeout ile gelen tüm değişken kapsam belirleme sorunları ile uğraşmak zorunda kalmadan kısa bir duraklama gerektiren bir Düğüm komut satırı aracı oluşturuyor olabilir. - Phil LaNasa


Bunun biraz eski bir soru olduğunu biliyorum, ama (benim gibi) Rhino ile Javascript kullanıyorsan, ...

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.
   */
}

109



Bu Java'ya bir çağrı mı? - Ken Sharp
Evet, Java'nın thread uykusuna bir çağrı. - mjaggard
Bu Java değil JavaScript - RousseauAlexandre
@RousseauAlexandre Yanlış. Bu JavaScript Rhino kullanarak (o zaman, bu günlerde Nashorn da eşit olabilir) - mjaggard


JQuery kullanıyorsanız, aslında setTimeout için bir sarıcıdan başka bir şey olmayan bir "gecikme" eklentisi yaratıldı:

// 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 dizi işlev çağrısında kullanabilirsiniz.

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

65



Bu kötü bir çözüm değil. Bağlam ve zincirlenebilirliği korur. - Nosredna
JQuery 1.4’den itibaren .delay() jQuery'nin bir parçası (yukarıdaki uygulamadan farklı anlamıyla olsa da). api.jquery.com/delay - Matt Ball
Bu sorunun kesinlikle eksik olduğu bir jQuery cevap. Bu yüzden aldık sevindim! - xDaizu
İki bağımsız arama arasında bir gecikmeye ihtiyacınız varsa, evet. Döngüyü yavaşlatmak için gecikmelere ihtiyacınız varsa, hayır. - WGroleau


Ben de uyku çözümü için 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 burada istemci tarafı çözümleriyle başka bir bağlantı var: http://www.devcheater.com/

Ayrıca, aradığınızda alert()uyarısı gösterilirken, kodunuz da duraklatılacak - uyarıyı görüntülememenin bir yolunu bulmanız ama aynı etkiyi almanız gerekiyor. :)


42



Katılıyorum, birçok insan "Hayır, bunu üretim kodunda yapma!" Diyorlar. Evet, istemiyorum. Bunu, deneme test kodunda yapmak istiyorum ve sonuç olarak, zarif bir çözüm üretmek için çok fazla zaman harcamak istemiyorum. - user435779
Bu bağlantı soruyu yanıtlayabilirken, cevabın temel kısımlarını buraya dahil etmek ve referans için bağlantı sağlamak daha iyidir. Bağlantılı sayfa değiştiğinde yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan - Adelin


Hadi bakalım. Kodun dediği gibi, kötü bir dev olma ve bunu web sitelerinde kullanma. Bu bir geliştirme programı işlevi.

// 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) {}
}

28



Bu temelde OP'inkiyle aynı şey. - Andrew Barber
Daha kesin olmak gerekirse, OP bir ALTERNATİF için sordu. - WGroleau
Çözüm iyi değil, bazı yerlerde async/await Maalesef cevap vermiyor ve bunu zorunlu olarak kullanmak zorundayız. - Nabi K.A.Z.