Сон в JavaScript - задержка между действиями

Есть ли способ, которым я могу заснуть в JavaScript до того, как он выполнит другое действие?

Пример:

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

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

2018 Обновление

Последние Safari, Firefox и Node.js теперь также поддерживают асинхронные/ожидающие/обещания.

Обновление 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();

Ответ 5

Если вам нужны менее громоздкие функции, чем 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 been a second");
    after(1000, function(){
        console.log("it been another second");
    });
});

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

Ответ 6

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

async yourAsynchronousFunction () {

    var a = 1+3;

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

    var b = a + 4;

}

Ответ 7

Существует несколько способов решения этой проблемы. Если мы используем функцию 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

Ответ 8

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

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

Ответ 9

Попробуйте эту функцию:

function delay(ms, cb) { setTimeout(cb, ms) }

Если вы используете Babel:

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

Вот как вы используете это:

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

Здесь демо.