Спи в JavaScript - задержка между действиями - PullRequest
111 голосов
/ 17 апреля 2009

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

Пример:

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

Ответы [ 9 ]

123 голосов
/ 17 апреля 2009

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

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

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

40 голосов
/ 10 января 2015

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

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

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

11 голосов
/ 28 июня 2016

Версия 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
)
7 голосов
/ 11 января 2017

2018 Обновление

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

2017 Обновление

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

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

'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 ()? , когда запрашивающая сторона запрашивает реальный сон (никакого другого выполнения кода на процесс), а не задержка между действиями.

3 голосов
/ 16 июля 2016

Если вам нужно меньше неуклюжих функций, чем 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 миллисекунд, ...")

2 голосов
/ 30 августа 2018

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

async yourAsynchronousFunction () {

    var a = 1+3;

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

    var b = a + 4;

}
0 голосов
/ 16 марта 2019

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

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

Вот демоверсия .

0 голосов
/ 10 июня 2018

Это моя модель, которая показывает, как "спать" или "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>
0 голосов
/ 31 июля 2017

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

Для получения более подробной информации о setTimeout() перейдите по этой ссылке .

Упрощенная версия:

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

Выход:
а = 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);
}

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



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

Chrome     Firefox     Edge     Safari     Opera
1.0        1.0         4.0      1.0        4.0
...