睡在JavaScript中-动作之间的延迟


129

在执行另一项操作之前,有没有办法可以在JavaScript中进行睡眠?

例:

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

Answers:


140

您可以使用setTimeout实现类似的效果:

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

这并不是真正的“休眠” JavaScript,它只是setTimeout在一定时间(以毫秒为单位)后执行传递给函数。尽管可以为JavaScript编写睡眠函数,但最好尽可能使用setTimeout它,因为它不会在睡眠期间冻结所有内容。


9
还可以看一下setInterval()。它类似于setTimeout(),但是您的函数被多次调用(直到停止它),如果您想在睡眠时做一些事情(例如进行进度更新,保持某些内部状态或其他任何操作),则此功能很有用。
Anders Sandvig

5
这不能回答问题。这个问题要求一个等效的“睡眠”,而事实并非如此。
felwithe '16

尽管此答案与问题所要求的不匹配,但它比循环和比较Date.now()更有用。没人使用阻塞循环的工具睡觉。
李春林

2
除非,当然,阻挡环路正是有人想什么。
桑科旺子(Wonko the Sane),

55

万一你真的需要一个sleep()公正的东西来测试。但是请注意,调试时大多数情况下它会使浏览器崩溃-也许这就是您仍然需要它的原因。在生产模式下,我将注释掉此功能。

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

new Date()除非您要浪费内存,处理能力,电池以及可能使用寿命的设备,否则请不要循环使用。


8
这个答案值得更多投票。给问题加注星标仅是该答案的原因。
jagc '16

那“递归过多”警告呢?
奥基·伊利·里纳尔迪

1
@OkiErieRinaldi那里没有递归,只是一个循环。
罗德里戈

7
@ 3.1415926535897932384626433833好吧,有人要求“睡眠”功能,这就是这里的内容。我用过一次,不记得确切地进行了哪种调试。如果我再次需要它,我将确切知道在哪里可以找到它。如果您喜欢其他功能,那是您的选择。能够选择不是很好吗?
罗德里戈

2
“忙碌中等待”。
Zeek2

13

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

功能*

()=>箭头功能

您还可以通过Promises链接事件:

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
)


11

2018更新

最新的Safari,Firefox和Node.js现在也支持异步/等待/承诺。

使用异步/等待/承诺:

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

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

请注意,这两种解决方案本质上都是异步的。这意味着myAsyncFunc(在两种情况下)将在睡眠时返回。

重要的是要注意,这个问题不同于sleep()的JavaScript版本是什么?请求者请求真正的睡眠(进程中没有其他代码执行),而不是动作之间的延迟。


1
到目前为止最好的答案!我已经花了30分钟在各处搜寻,以找到那个。
538ROMEO

1
我在寻找解决方案时错过了这个答案,然后重新发明了自行车:D如果仅在能节省时间之前我会看到它!已投票!
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(); };将让您let asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);使用sleep()第二个代码块中的定义。
Patrick Roberts

3

如果您想要比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

另一种方法是使用Promise和setTimeout(请注意,您需要位于函数内部,并使用async关键字将其设置为异步):

async yourAsynchronousFunction () {

    var a = 1+3;

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

    var b = a + 4;

}

2

这是一种非常简单的方法,感觉像同步的睡眠/暂停一样,但是是合法的js异步代码。

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

您可以使用普通的javascript,这将在5秒钟后调用您的函数/方法:

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

0

有几种方法可以解决此问题。如果我们使用该setTimeout功能,让我们首先了解它。 此函数具有三个参数:functioncodedelay(以毫秒为单位)和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

0

这是我的模型,展示了如何使用生成器函数(ES6)在javascript中“睡眠”或“ DoEvents”。注释代码:

<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

试试这个功能:

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

使用方法如下:

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

还是去承诺风格:

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

这是一个演示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.