JavaScript'te Uyku - eylemler arasında gecikme


129

JavaScript'te başka bir eylem gerçekleştirmeden önce uyuyabilmemin bir yolu var mı?

Misal:

 var a = 1+3;
 // Sleep 3 seconds before the next action here
 var b = a + 4;

Yanıtlar:


140

setTimeoutBenzer bir efekt elde etmek için kullanabilirsiniz :

var a = 1 + 3;
var b;
setTimeout(function() {
    b = a + 4;
}, (3 * 1000));

Bu gerçekten JavaScript'i 'uyutmaz' - sadece setTimeoutbelirli bir süre sonra (milisaniye cinsinden belirtilir) aktarılan işlevi çalıştırır . JavaScript için bir uyku işlevi yazmak mümkün olsa da, setTimeoutuyku süresi boyunca her şeyi dondurmadığından mümkünse kullanmak en iyisidir .


9
Ayrıca setInterval () 'a bir göz atın. SetTimeout () 'a benzer, ancak işleviniz birden çok kez çağrılır (siz onu durdurana kadar), bu, uyurken bir şeyler yapmak istiyorsanız yararlıdır (ilerleme güncellemeleri yapmak, bazı iç durumları korumak veya her neyse).
Anders Sandvig

5
Bu soruya cevap vermiyor. Soru, bunun olmadığı bir "uyku" eşdeğeri sorar.
felwithe

Bu cevap sorulan soru ile uyuşmasa da, döngüden daha kullanışlıdır ve Date.now () ile karşılaştırılır. Bir tıkalı döngü ne kullanacağını kimse uyku moduna geçirmez.
Li Chunlin

2
Tabii ki, engelleme döngüsü tam olarak birinin istediği şey değilse.
Wonko the Sane

55

Bir sleep()şeyi test etmek için gerçekten ihtiyacınız olursa diye. Ancak hata ayıklama sırasında çoğu zaman tarayıcıyı çökerteceğini unutmayın - muhtemelen bu yüzden yine de ihtiyacınız vardır. Üretim modunda bu işlevi yorumlayacağım.

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

new Date()Hafızayı, işlem gücünü, pili ve muhtemelen cihazınızın ömrünü boşa harcamak istemediğiniz sürece döngü içinde kullanmayın .


8
Bu cevap daha fazla oyu hak ediyor. Sadece bu cevabın nedeni soruya yıldız eklemek.
jagc

"çok fazla özyineleme" uyarısına ne dersiniz?
Oki Erie Rinaldi

1
@OkiErieRinaldi Orada özyineleme yok, bu sadece bir döngü.
Rodrigo

7
@ 3.1415926535897932384626433833 Birisi "uyku" işlevi istedi, işte burada olan bu. Bir kez kullandım, tam olarak ne tür bir hata ayıklama için hatırlayamıyorum. Bir daha ihtiyacım olursa, tam olarak nerede bulacağımı biliyorum. Başka bir işlevi tercih ederseniz, bu sizin seçiminizdir. Seçim yapabilmek harika değil mi?
Rodrigo

2
"Meşgul bekliyor".
Zeek2

13

ECMAScript 6 sürümü, "kod engelleme" için verimli üreteçler kullanan:

Asıl soru yedi yıl önce gönderildiği için, tam kodla cevaplamakla uğraşmadım çünkü çok kolay ve zaten cevaplanmış. Bu, en az iki uykuya ihtiyacınız varsa veya eşzamansız yürütmeyi sıralamayı planlıyorsanız, daha karmaşık sorunlarda yardımcı olacaktır. İhtiyaçlarınıza uyacak şekilde değiştirmekten çekinmeyin.

let sleeptime = 100
function* clock()
{
    let i = 0
    while( i <= 10000 )
    {
        i++
        console.log(i); // actually, just do stuff you wanna do.
        setTimeout(
            ()=>
            {
                clk.next()
            }
            , sleeptime
        )
        yield
    }
}

let clk = clock()
clk.next()

fonksiyon *

() => ok işlevi

Ayrıca Promises aracılığıyla etkinlikleri zincirleyebilirsiniz :

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


sleep(1000).then(function()
{
    console.log('1')
    sleep(1000).then(function()
    {
        console.log('2')
    })
})

Ya da çok daha basit ve daha az süslü bir yol olurdu

function sleep(ms, f)
{
    return(
        setTimeout(f, ms)
    )
}


sleep(500, function()
{
    console.log('1')
    sleep(500, function()
    {
        console.log('2')
    })
})
console.log('Event chain launched')

Sadece bir durumun olmasını bekliyorsan, böyle bekleyebilirsin

function waitTill(condition, thenDo)
{
    if (eval(condition))
    {
        thenDo()
        return
    }

    setTimeout(
        ()    =>
        {
            waitTill(condition, thenDo)
        }
        ,
        1
    )
}

x=0

waitTill(
    'x>2 || x==1'
    ,
    ()    =>
    {
        console.log("Conditions met!")
    }
)

// Simulating the change
setTimeout(
    () =>
    {
        x = 1
    }
    ,
    1000
)


11

2018 Güncellemesi

En son Safari, Firefox ve Node.js artık async / await / promises'i de destekliyor.

Async / await / Promises kullanma:

(1/2017 itibarıyla Chrome'da destekleniyor ancak Safari, Internet Explorer, Firefox, Node.js'de desteklenmiyor)

'use strict';

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

let myAsyncFunc = async function() {
  console.log('Sleeping');
  await sleep(3000);
  console.log('Done');
}

myAsyncFunc();

2017 Güncellemesi

JavaScript, bu sorunun sorulmasından bu yana gelişti ve şimdi oluşturucu işlevlere sahip ve yeni async / await / Promise kullanıma sunuluyor. Aşağıda, biri tüm modern tarayıcılarda çalışacak jeneratör işlevli ve diğeri henüz her yerde desteklenmeyen yeni async / await kullanan iki çözüm var.

Bir jeneratör işlevinin kullanılması:

'use strict';

let myAsync = (g) => (...args) => {
    let f, res = () => f.next(),
        sleep = (ms) => setTimeout(res, ms);
    f = g.apply({sleep}, args); f.next();
};

let myAsyncFunc = myAsync(function*() {
    let {sleep} = this;
    console.log("Sleeping");
    yield sleep(3000);
    console.log("Done");
});

myAsyncFunc();

Bu iki çözümün de doğası gereği eşzamansız olduğuna dikkat edin. Bu, myAsyncFunc'un (her iki durumda da) uyurken geri döneceği anlamına gelir.

Bu sorunun, sleep () JavaScript sürümü nedir sorusundan farklı olduğuna dikkat etmek önemlidir. istekte bulunanın eylemler arasındaki gecikmeden ziyade gerçek uyku (işlemde başka kod yürütme yok) istemesi.


1
Şimdiye kadarki en iyi cevap !! Bunu bulmak için 30 dakika boyunca her yerde arama yaptım .. büyük teşekkürler !!!
538ROMEO

1
Bir çözüm ararken bu cevabı kaçırdım ve bisikleti yeniden icat ettim: D Keşke daha önce görsem saatler kazandırırdı !! Upvoted!
sserzant

let co = gen => (...args) => { let iter = gen(...args); let resume = () => new Promise((resolve, reject) => { let result = iter.next(); if (result.done) resolve(result.value); else Promise.resolve(result.value).then(resume).then(resolve, reject); }); return resume(); };ikinci kod bloğunuzdaki let asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);tanımını kullanmanıza izin verir sleep().
Patrick Roberts

3

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

Artık kolayca "N milisaniyeden sonra, ..." (veya "her N milisaniyede bir, ...") şeklinde okunuyor


2

Bunu yapmanın başka bir yolu da Promise ve setTimeout kullanmaktır (bir işlevin içinde olmanız ve async anahtar sözcüğüyle eşzamansız olarak ayarlamanız gerektiğini unutmayın):

async yourAsynchronousFunction () {

    var a = 1+3;

    await new Promise( (resolve) => {
        setTimeout( () => { resolve(); }, 3000);
    }

    var b = a + 4;

}

2

Eşzamanlı uyku / duraklama gibi 'hissettiren', ancak yasal js eşzamansız kod olan bunu yapmanın çok basit bir yolu.

// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))

async function main () {
    console.log('starting');
    // Call with await to pause.  Note that the main function is declared asyc
    await pause(3*1000)
    console.log('done');
}


1

Düz javascript kullanabilirsiniz, bu 5 saniye sonra işlevinizi / yönteminizi çağıracaktır:

setTimeout(()=> { your_function(); }, 5000);

0

Bu sorunu çözmenin birkaç yolu vardır. setTimeoutFonksiyonu kullanırsak, önce onu tanıyalım. Bu işlevin üç parametresi vardır: functionveya code, delay(milisaniye cinsinden) ve parameters. Yana fonksiyonu ya da kod parametre gereklidir, diğerleri isteğe bağlı olmaktadır. Gecikmeyi girmediğinizde, sıfır olarak ayarlanacaktır.

setTimeout() Bu bağlantıya git hakkında daha fazla ayrıntı için .

Basitleştirilmiş sürüm:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){ 
    b = a + 4; 
    console.log('b = ' + b);
}, 1000);

çıktı:
a = 4
24 -> Etkin zaman aşımları listesinin numara tanımlayıcısı
b = 8


Parametre geçişini kullanarak:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);

function myFunction(a)
{
    var b = a + 4;
    console.log('b = ' + b);
}

çıktı:
a = 4
25 -> Etkin zaman aşımları listesinin numara tanımlayıcısı
b = 8



Tarayıcı Desteği:

Chrome Firefox Edge Safari Opera
1.0 1.0 4.0 1.0 4.0

0

Bu, bir jeneratör işlevi (ES6) kullanarak javascript'te nasıl "uyuyacağını" veya "DoEvents" i gösteren modelimdir. Yorumlanan kod:

<html>
<head>
<script>
  "use strict"; // always
  // Based on post by www-0av-Com /programming/3143928
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
  var divelt, time0, globaln = 0; // global variables
  var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
  divelt = document.getElementsByTagName("body")[0]; // for addline()
  addline("typeof Main: " + typeof Main);
  addline("typeof MainDriver: " + typeof MainDriver);
  addline("typeof MainGenObj: " + typeof MainGenObj);
  time0 = new Date().valueOf(); // starting time ms
  MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
  // could be loops, or inline, like this:

  addline("Part A, time: " + time() + ", " + ++globaln); // part A
  yield 2000;                    // yield for 2000 ms (like sleep)

  addline("Part B, time: " + time() + ", " +  ++globaln); // part B
  yield 3000;                    // yield for 3000 ms (or like DoEvents)

  addline("Part Z, time: " + time() + ", " +  ++globaln); // part Z (last part)
  addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
  var obj = MainGenObj.next(); // executes the next (or first) part of Main()
  if (obj.done == false) { // if "yield"ed, this will be false
    setTimeout(MainDriver, obj.value); // repeat after delay
  }
}
function time() { // seconds from time0 to 3 decimal places
  var ret = ((new Date().valueOf() - time0)/1000).toString();
  if (ret.indexOf(".") == -1) ret += ".000";
  while (ret.indexOf(".") >= ret.length-3) ret += "0";
  return ret;
}
function addline(what) { // output
  divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>

0

Bu işlevi deneyin:

const delay = (ms, cb) => setTimeout(cb, ms)

İşte onu nasıl kullanıyorsun:

console.log("Waiting for 5 seconds.")
delay(5000, function() {
  console.log("Finished waiting for 5 seconds.")
})

Veya söz stiline gidin:

const delay = ms => new Promise(resolve => {
    setTimeout(resolve, ms)
})

İşte bir demo .

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.