Sleep in JavaScript-задержка между действиями

есть ли способ сделать сон в JavaScript, прежде чем он выполнит другое действие?

пример:

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

8 ответов


можно использовать setTimeout для достижения аналогичного эффекта:

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

это на самом деле не "спящий" JavaScript-он просто выполняет функцию, переданную setTimeout после определенного времени (задается в миллисекундах). Хотя можно написать функцию сна для JavaScript, лучше использовать setTimeout если возможно, так как он не замораживает все во время сна.


В случае, если вам действительно нужен sleep() просто чтобы что-то проверить. Но имейте в виду, что он будет сбой браузера большую часть времени во время отладки - вероятно, поэтому вам это нужно в любом случае. В производственном режиме я прокомментирую эту функцию.

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

не используйте new Date() в цикле, если вы не хотите тратить память, вычислительную мощность, батарею и, возможно, срок службы вашего устройства.


версия ECMAScript 6, используя генераторы с выходом для "блокировки кода":

потому что первоначальный вопрос был опубликован семь лет назад, я не потрудился ответить на точный код, потому что это слишком просто и уже ответил. Это должно помочь в более сложных проблемах, например, если вам нужно хотя бы два сна или если вы планируете последовательность асинхронного выполнения. Не стесняйтесь изменять его под свои по необходимости.

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()

*

() => стрелка

вы также можете связывать события через обещания:

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')
    })
})

или гораздо проще и менее причудливый способ будет

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')

если вы просто ждете какого-то условия, чтобы произойти, вы можете ждать, как это

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
)

обновить 2018

последние Safari, Firefox и узел.js теперь также поддерживают async/await / promises.

обновление 2017

JavaScript эволюционировал с тех пор, как этот вопрос был задан, и теперь имеет функции генератора, и новый async/await/Promise развертывается. Ниже приведены два решения, одно с функцией генератора, которая будет работать во всех современных браузерах, а другое, используя новый async / await, который еще не поддерживается повсюду.

использование функции генератора:

'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();

использование async / await / Promises:

(по состоянию на 1/2017, поддерживается в Chrome, но не в Safari, Internet Explorer, Firefox, Node.в JS)

'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();

обратите внимание на то, что оба эти решения являются асинхронными по своей природе. Это означает, что myAsyncFunc (в обоих случаях) вернется во время сна.

важно отметить, что этот вопрос отличается от что такое JavaScript-версия sleep ()? где запрашивающий запрашивает реальный сон (никакого другого выполнения кода в процессе), а не задержку между действиями.


если вы хотите меньше неуклюжих функций, чем setTimeout и setInterval, вы можете обернуть их в функции, которые просто меняют порядок аргументов и дают им хорошие имена:

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

версии CoffeeScript:

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

затем вы можете использовать их красиво с анонимными функциями:

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

теперь он легко читается как " после N миллисекунд, ..."(или "каждые N миллисекунд ...")


существует несколько способов решения этой проблемы. Если мы используем setTimeout функция, давайте сначала узнаем об этом. эта функция имеет три параметра: function или code, delay (в миллисекундах) и parameters. С функции или код параметр необходим, другие опционные. Как только вы не вошли в задержка, он будет установлен в нуль.

подробнее о setTimeout() перейти по этой ссылке.

упрощенный вариант:

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

выход:
a = 4
24 --> идентификатор номера списка активных таймаутов
b = 8


Использование параметра pass:

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

выход:
a = 4
25 --> идентификатор номера списка активных тайм-аутов
b = 8



Поддержка Браузера:

Chrome     Firefox     Edge     Safari     Opera
1.0        1.0         4.0      1.0        4.0

Это моя модель, которая показывает, как" спать "или" DoEvents " в javascript с помощью функции генератора (ES6). Комментарий code:

<html>
<head>
<script>
  "use strict"; // always
  // Based on post by www-0av-Com https://stackoverflow.com/questions/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>

другой способ сделать это-использовать Promise и setTimeout (обратите внимание, что вам нужно быть внутри функции и установить ее как асинхронную с ключевым словом async):

async yourAsynchronousFunction () {

    var a = 1+3;

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

    var b = a + 4;

}