sleep()的JavaScript版本是什么?


2335

是否有sleep比下面的pausecomp函数(从此处获取)更好的方法来设计JavaScript ?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

这不是JavaScriptSleep的重复-动作之间的延迟 ; 我希望在函数中间真正入睡,而不是在执行一段代码之前没有延迟。


4
它是在一段时间内设置的,如果我使用setTimeout,则while将继续处理并排队更多setTimeouts,这些setTimeouts最终将同时运行,并使彼此之间并发一些
fmsf

158
这是一个可怕的解决方案-您将无所事事地减少处理周期。

12
睡眠的唯一目的是轮询或等待回调-setInterval和setTimeout都比这更好。
annakata

1
可能您可以使用JavaScript中的延续传递样式来完成您想要的事情。看一下这篇文章。
Ognyan Dimitrov

Answers:


2559

2017年— 2019年更新

自2009年提出这个问题以来,JavaScript取得了长足的发展。现在,所有其他答案都已过时或过于复杂。这是当前的最佳做法:

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

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

就是这个。await sleep(<duration>)

还是单线:

await new Promise(r => setTimeout(r, 2000));

注意,

  1. await只能在带有async关键字前缀的函数中执行,或者在某些环境中(例如Chrome DevTools控制台或Runkit)在脚本的顶层执行。
  2. await仅暂停当前async功能

两个新的JavaScript功能帮助编写了此“睡眠”功能:

兼容性

如果您正在使用节点年纪比7(已经达成了一些奇怪的原因生命的尽头),或瞄准旧的浏览器,async/ await仍然可以通过使用巴别塔(一种工具,将transpile的JavaScript +新功能集成到普通的旧的JavaScript) ,带有transform-async-to-generator插件。


5
好东西。我想知道,在JS调用“睡眠”模式后,这对现代浏览器的“活动” /“非活动”状态有何影响或相关?浏览器是否可以按一般JS的预期阻止睡眠,以便在变为“活动”状态时重新调用,或者它具有不同的行为?
安德烈·卡尼略

18
当前的浏览器对此有什么支持?在绝大多数浏览器或至少所有常见浏览器支持该解决方案之前,我不会认为以前的解决方案是“过时的”。相反,在获得广泛支持之前,我认为此解决方案很有趣,但不可行/不切实际。
阿尔文·汤普森

74
这不是“真正的睡眠”,也无法回答问题。被问到的人清楚地将stackoverflow.com/questions/758688/sleep-in-javascript和他的问题区分开来。在实际睡眠中,无法执行其他代码(除非在其他线程中)。这个答案对其他问题也有好处。
niry

4
@jacroe-编译器处理箭头功能以及异步/等待(无论如何都会导致IE呕吐血液)
Jaromanda X

11
@niry JavaScript是一种单线程语言,因此不适合“真正的”睡眠,因为它在与UI相同的线程上运行,并且会导致无响应的网页。
Patrick Roberts

849

(请参阅2016年更新的答案

我认为执行一个动作,等待,然后执行另一个动作是完全合理的。如果您习惯于使用多线程语言编写代码,那么您可能会想到在一段特定的时间内让执行程序唤醒您的线程。

这里的问题是JavaScript是基于单线程事件的模型。虽然在特定情况下,让整个引擎等待几秒钟可能会很好,但通常这是一种不好的做法。假设我想在编写自己的函数时使用您的函数?当我调用您的方法时,所有方法都会冻结。如果JavaScript可以某种方式保留函数的执行上下文,将其存储在某个地方,然后将其带回并稍后再继续,则可能会发生睡眠,但这基本上就是线程化。

因此,您几乎完全可以遵循别人的建议-您需要将代码分解为多个功能。

那么,您的问题是一个错误的选择。您无法以自己想要的方式入睡,也不应追求您建议的解决方案。


45
这根本不是一个正确的答案。如果Javascript没有睡眠功能,那仅仅是因为ECMAScript不需要它。这是负责Javascript设计的机构的设计选择。可以确定Javascript运行时在运行下一行代码之前要等待给定的时间,但是选择不这样做。
Didier A.

5
睡眠可以用JavaScript完美实现,尽管它不具有实时精度。毕竟,这是一个基于事件的系统。如果异步调用完成,则会触发事件。我看不出为什么在发出sleep()之后无法将其返回给浏览器,直到睡眠结束,然后再将控制权返回给调用函数的原因是不可能的。是的,我也同意,有时候睡觉很方便,尤其是在开发人员严重破坏设计之前,除了完全重构之外,您再也没有其他办法了
Lawrence 2013年

尝试Hypnotic,它遵循以下想法:coolwanglu.github.io/hypnotic/web/demo.html
Tezcat 2013年

4
调用javascript单线程是一个神话。尽管从技术上讲可能是正确的,但在功能上却像多线程语言。模拟fork()非常容易,尽管yield()并不是真正可实现的,但您可以通过使用共享内存来锁定/信号量来达到非常接近的效果。对于普通程序员而言,将其视为多线程是有意义的。技术名称仅对语言的开发人员重要。
Benubird

8
我同意为什么sleep()在JS中无法实现,而且大多数时候都有更好的方法来做事情。但是我仍然会认为引擎将所有事物联系在一起的方式是设计缺陷。没有任何理由,如果没有sleep()引擎破坏CPU并像疯子一样冻结应用程序,该语言就无法具有限于特定脚本,页面或函数的功能。现在是2015年,您不应该使用崩溃整个Web浏览器while(1)。我们有Flash这样的东西。
Beejor 2015年

660

在JavaScript中,我重写了每个函数,以便可以尽快结束。您希望浏览器重新控制,以便可以更改DOM。

每次我想在函数中间睡觉时,我都会重构为使用setTimeout()

编辑

在任何语言中臭名昭著的睡眠或延迟功能都引起了很大的争议。有些人会说应该总是有信号或回调来触发给定的功能,另一些人会说有时任意的延迟时间是有用的。我说,在这个行业中,对每个人来说,一条规则永远不能决定任何事情。

编写睡眠函数非常简单,并且可以在JavaScript Promises中使用:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
通过关闭的方式。 function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
混乱

68
好的,如果该代码不打算在网页中使用该怎么办?
EugenioMiró10年

10
@EugenioMiró如果代码不打算在网页中使用,请让主机的对象模型实现sleep方法。-我认为问题是针对DOM的,该DOM暴露于网页上运行的javascript。
BrainSlugs83 2011年

31
@Nosredna是的,我们知道如何进行异步调用,这对我们sleep()没有帮助。我希望以特定顺序进行呼叫,并以特定顺序恢复数据。我在一个for循环中有5个层次。我想阻止执行。真正的睡眠方法不会“降低浏览器的速度”,睡眠之手可以将控制权返回给浏览器以及在CPU仍处于阻塞状态时需要CPU时间的任何其他线程。
BrainSlugs83 2011年

382
这不是问题的答案。
TMS

302

仅用于debug / dev,如果对某人有用,我将其发布

有趣的是,在Firebug(可能还有其他js控制台)中,仅在指定的睡眠持续时间之后,按Enter键之后什么也没有发生(...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

使用示例:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
这不是答案。它与问题中的代码完全相同,只是略短一些。
jab 2015年

16
忙着等待,真的吗?在JS中?几秒钟?如果我发现有这样做的网站,它将被阻止。
mafu

34
@mafu这就是为什么它说only for debug/dev... rolleyes
xDaizu

11
绝对不要这样做。这将使CPU在其执行的内核上命中100%并将其阻塞。
noego

3
这在命令行javascript应用程序中很有用,并且可能是唯一的睡眠方式,因为async / await并没有帮助。
Wheezil '18

177

我同意其他海报,繁忙的睡眠只是一个坏主意。

但是,setTimeout不会阻止执行,它会在SET超时后立即执行函数的下一行,而不是在超时到期后立即执行,因此不会完成与睡眠相同的任务。

做到这一点的方法是将您的功能分解为前后各部分。

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

确保您的函数名称仍然准确地描述每个部分的功能(例如,IE GatherInputThenWait和CheckInput,而不是funcPart1和funcPart2)

编辑

这种方法的目的是直到超时后才执行您决定的代码行,同时仍将控制权交还给客户端PC以执行其排队的其他内容。

进一步编辑

正如评论中指出的那样,这绝对不会循环工作。您可以进行一些怪异的(丑陋的)黑客攻击,使其循环运行,但总的来说,这只会造成灾难性的意大利面条式代码。


12
是的 棘手的地方是循环,甚至是嵌套循环。您必须放弃for循环,而要使用计数器。
Nosredna

触摸。我的意思是,这仍然可能,但在那种情况下却很丑陋。您还可以使用一些静态布尔状态变量,但这也很hackhack。
DevinB,2009年

2
-1。同样,这不能回答问题。这更多是针对“如何异步执行功能”之类的问题的答案,该问题与“如何阻止代码执行”有很大不同。
Deepak GM

6
@Nosredna不,您可以使用闭包。例如: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }和-X for(var X = 0; X < 3;X++) { foo(X); }传递到中foo,然后在最终调用index时以名称重用foo_continue
Izkata 2014年

2
@Alexander当然可以,因为setTimeout()的目的是防止浏览器通过异步运行代码而锁定。将console.log()内部放入foo_continue()setTimeout版本中,您将获得相同的结果。
2015年

132

出于对$ DEITY的热爱,请不要进行繁忙的睡眠功能。 setTimeoutsetInterval做您需要的一切。

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

每两秒钟间隔将文本隐藏一秒钟。这显示了如何使用setInterval和setTimeout每秒显示和隐藏文本。


3
好吧,不是所有的东西:setInterval对轮询的印象要好得多。
annakata 2009年

3
那段代码不会在JavaScript引擎中阻止什么?
Deniz Dogan

10
除非您需要使睡眠同步,否则这是一个完全有效的问题。
亚伦·杜福尔

36
我认为我们很多人可能会忘记JavaScript不是仅用于浏览器的语言。这个家伙可能正在创建一个Node命令行实用程序,该实用程序需要短暂的暂停,而无需处理setTimeout附带的所有变量作用域问题。
Phil LaNasa 2014年

3
@PhilLaNasa:如果句法关闭仍然令人恐惧,那么一个人就必须认真地折腰并通过节点101进行工作。–
混乱

113

我知道这是一个古老的问题,但是如果(像我一样)您在Rhino上使用Javascript,则可以使用...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

4
这是对Java的呼吁吗?
肯·夏普

14
这是Java的使用Javascript
RousseauAlexandre

18
@RousseauAlexandre错误。它是使用Rhino的JavaScript(当时,这些天可能就是Nashorn)
mjaggard '18年

71

如果您使用的是jQuery,则实际上有人创建了一个“延迟”插件,该插件不过是setTimeout的包装器:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

然后,您可以按预期在一行函数调用中使用它:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
这不是一个不好的解决方案。保持上下文和可链接性。
Nosredna

39
从jQuery 1.4开始,它.delay()是jQuery的一部分(尽管其语义与上述实现不同)。api.jquery.com/delay
Matt Ball,

7
这个问题绝对缺少的是jQuery答案。很高兴我们得到了!
xDaizu

1
如果您需要两次独立通话之间的延迟,可以。如果您需要延迟来减慢循环速度,则不会。
WGroleau '18年

46

我也搜索了睡眠解决方案(不是用于生产代码,仅用于开发/测试),并找到了这篇文章:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

...这是客户端解决方案的另一个链接:http : //www.devcheater.com/

另外,在调用时alert(),代码也会暂停,同时显示警报-需要找到一种不显示警报但获得相同效果的方法。:)


35
我同意,很多人都在说:“不,不要在生产代码中这样做!” 是的,嗯,我不想。我想用一次性的测试代码来做,因此,我不想花很多时间来做一个优雅的解决方案。
user435779 2012年

31

这是使用同步XMLHttpRequest的简单解决方案:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

sleep.php的内容:

<?php sleep($_GET['n']);

现在调用它:sleep(5);


5
@lukad,setTimeout()如果可行,请使用,但如果这样做意味着拆开1000行回调,这可能看起来像不是在开玩笑。
pguardiario

11
不幸的是,非异步XMLHttpRequests已被弃用,并且将来会被删除。这很有趣,因为事实是首先导致我提出这个问题的。
Beejor 2015年

这实际上是IMO的一个好主意。尽管我认为睡眠API(请求URL)不应该公开,因为它可能会被滥用。
Vahid Amiri

@Beejor总是只考虑未来,意味着生活在未来主义的无聊中:-)
user1742529

很好,但是您是否知道某个时间互联网速度慢还是网站ping时间长于睡眠脚本的时间超过了争论时间。就像您使用sleep(300)网站使网站花费150毫秒进行响应一样,JavaScript代码会休眠450毫秒。如果浏览器无法连接互联网,则只能使用0毫秒。所以这不是更好的解决方案
H Chauhan

30

干得好。正如代码所言,不要做坏开发者,并在网站上使用它。这是一个开发实用程序功能。

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

17
这基本上与OP相同。
安德鲁·巴伯

5
更确切地说,这就是OP要求替代的内容。
WGroleau

解决方案不好,但是在某些地方 async/await不幸的它没有响应,我们必须强制使用它。
纳比·卡兹

21

我个人喜欢简单的方法:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

然后:

sleep(2); // Sleeps for 2 seconds

我一直在使用它来在P5js中创建脚本时创建假加载时间


3
我认为这是主要问题的最优化版本:它在循环内不做任何数学运算,只是一个简单的比较。这有点难读。
hegez

4
从来没有这样做。在此功能运行时,您是否检查过CPU使用率?如果您有足够的时间进行操作,则应接近100%。
noego

2
@hegez:鉴于循环无论如何都将在固定的墙上时钟时间内运行,因此似乎似乎最优化循环。
ShadowRanger

@noego怎么样?我刚刚在Node 10上进行了测试,我根本没有CPU使用率的变化
melMass

@melMass通过使CPU 100%繁忙,此功能仅阻塞n秒钟的Node线程。由于以下两个原因(阻塞+ CPU杀手),此“解决方案”是一个非常糟糕的主意。等待HAS是非阻塞的,因此是异步的。
Jeremy Thille

20

第一:

定义要执行的函数,如下所示:

function alertWorld(){
  alert("Hello World");
}

然后使用setTimeout方法安排其执行:

setTimeout(alertWorld,1000)

注意两件事

  • 第二个参数是时间(以毫秒为单位)
  • 作为第一个参数,您只需要传递函数的名称(引用),而不带括号

18

使事物看起来像大多数人想要的更好的解决方案是使用匿名函数:

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

这可能是您所要做的事情最接近的东西。

请注意,如果您需要多次睡眠,那么这可能会很麻烦,您可能实际上需要重新考虑设计。


这是在台式机浏览器和较旧的手机上为我工作的一款。我尝试过的其他方法并不能全部解决。
迈克


10

对于浏览器,我同意setTimeout和setInterval是必经之路。

但是对于服务器端代码,它可能需要阻止功能(例如,因此您可以有效地进行线程同步)。

如果使用的是node.js和流星,则可能会遇到在光纤中使用setTimeout的限制。这是服务器端睡眠的代码。

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

参见:https : //github.com/laverdet/node-fibers#sleep


Server may require a blocking function...我看不出有多么强力地阻塞Node的唯一线程并使整个服务器几秒钟无响应是一个好主意,但无论如何
Jeremy Thille

10

我将setTimeOut封装在Promise中以实现与其他异步任务的代码一致性:Fiddle中的 Demo

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

这样使用:

sleep(2000).then(function() { 
   // Do something
});

如果您曾经使用Promises,很容易记住语法。


4
为什么这比仅使用setTimeout(function(){/ *做某事* /},2000);还要好?
JSideris '16

10

使用Atomics.wait更新2019

应该在Node 9.3或更高版本中工作。

我在Node.js中需要一个非常准确的计时器,因此非常有用。但是,似乎浏览器中的支持非常有限。

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

运行了10秒的计时器基准测试。

使用setTimeout,我得到的错误最多为7000微秒。(7毫秒)

使用Atomics,我的错误似乎保持在600微秒以下。(0.6毫秒)

2020年更新:摘要

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

其中一个服务器端页面(例如sleep.jsp)看起来像

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

在我看来,这比公认的解决方案要好得多,在没有调用者的异步/等待的情况下,该解决方案无法实现为简单的功能。
GroovyDotCom

是的,只要您知道这会阻塞并且通常不是一件好事
Kapytanhook

挺酷的,但是事实上只有Chrome和Firefox才真正支持此功能,但这并不适合在网络上使用。(2019年11月)
JGreatorex

9

这里的大多数答案都是错误的,或者至少是过时的。没有理由让javascript必须是单线程的,实际上不是。如今,所有主流浏览器都支持工作程序,在此之前,其他JavaScript运行时(如Rhino和Node.js)都支持多线程。

“ JavaScript是单线程”不是有效的答案。例如,在worker中运行sleep函数不会阻止ui线程中运行的任何代码。

在支持生成器和yield的较新运行时中,可以在单线程环境中为sleep函数带来类似的功能:

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);

模仿睡眠不同于真正的睡眠功能,因为它不会阻塞线程。它只是javascript当前setTimeout函数之上的糖。此功能类型已在Task.js中实现,并且今天应在Firefox中工作。


IE至少没有通过版本10在IE中实现,而IE 10当前代表了大量的用户。
Beejor 2015年

是的,即使如此,sleep使用多个工作程序来实现也是不切实际的。如果使用Node.js,则生成器功能已经实现,可以按照说明使用。截至目前,主流浏览器尚未全部实现生成器。
加百利·拉特纳2015年

8

我已经搜索/搜索了很多关于javascript sleep / wait的网页...如果您想让javascript“运行,延迟,运行”,则没有答案。大多数人得到的是“运行,运行(无用)。东西”,“运行”或“运行,运行+延迟运行”...。

因此,我吃了一些汉堡,然后开始思考:::这是一个可行的解决方案...但是您必须将正在运行的代码切碎... :::是的,我知道,这只是一个易于阅读的重构。还是...

// ............................................ // example1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

// .................................... // example2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

// ................. example3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

// .............. example4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>

5
好的,这可以与setTimeput一起使用,但是很难看到发生了什么。使用setTimeout本身比这更容易。
naugtur 2011年

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

这和真实的问题是一样的。使其成为真正的答案没有多大意义。
EML 2014年

2
这不是一个很好的解决方案-在Selenium的JavaScriptExecutor中使用此功能可使Chrome浏览器在2104 MacBook Pro上挂起我的Chrome浏览器的时间大约占50%。
2015年

7

没有任何依赖关系的最短解决方案:

await new Promise(resolve => setTimeout(resolve, 5000));

在IE11中不起作用。我们收到箭头功能的语法错误。
DDphp

@ Java-DK使用await new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

您无法像在JavaScript中那样进行睡眠,或者,您不应这样做。运行睡眠或while循环将导致用户的浏览器挂起,直到循环完成。

使用您所引用的链接中指定的计时器。


6

您可能需要sleep()函数而不是使用setTimeout()的一种情况是,如果您有一个函数可以响应用户的单击,最终将最终打开一个新的弹出窗口,并且您已经启动了一些需要短时间的处理在显示弹出窗口之前完成。将打开的窗口移到关闭窗口中通常意味着它会被浏览器阻止。


6

如果您必须处理同步执行,我可以理解睡眠功能的用途。setInterval和setTimeout函数创建一个并行执行线程,该线程将执行顺序返回给主程序,如果您必须等待给定的结果,则该方法无效。当然,可以使用事件和处理程序,但是在某些情况下不是想要的。


6

加我的两位。我需要等待测试。我不想拆分代码,因为这会花费很多工作,所以对我来说很简单。

for (var i=0;i<1000000;i++){                    
     //waiting
  }

我认为这样做没有任何弊端,对我来说是成功的秘诀。


可能会被编译掉。
维克多·塞尔

请不要这样做。这是一个阻塞的睡眠调用,这意味着当您的代码占用JS线程时,无法运行其他JavaScript。
史蒂夫·米德利

5
@SteveMidgley“在您的代码占用JS线程的同时,没有其他JavaScript [能够]运行”在我看来正是OP想要做的事情__(ツ)_ //
drigoangelo

1
我只是进行了一些测试,结果似乎是一个空循环也会阻塞浏览器和CPU(而不仅仅是JavaScript)。for无论使用的最大值如何i,甚至使用内部放置的复杂数学代码,使用循环都几乎总是立即执行。因此,除非您只等待几毫秒,否则似乎仍然无法在JS中正常睡眠。
Beejor 2015年

100万太大了。对我来说足够10k
Vlad

6

可以使用Java的sleep方法来完成。我已经在FF和IE中对其进行了测试,它不会锁定计算机,消耗资源或导致服务器连续命中。对我来说似乎是一个干净的解决方案。

首先,您必须在页面上加载Java并使其可用。为此,我这样做:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

然后,当您想要轻松地暂停JS时,您要做的就是:

java.lang.Thread.sleep(xxx)

其中xxx是时间(以毫秒为单位)。就我而言(作为理由),这是一家非常小的公司的后端订单履行的一部分,我需要打印必须从服务器加载的发票。我是通过将发票(作为网页)加载到iFrame并打印iFrame来实现的。当然,我必须等到页面完全加载后才能打印,因此JS必须暂停。我通过使发票页面(在iFrame中)通过onLoad事件更改了父页面上的隐藏表单字段来实现了这一点。父页面上用于打印发票的代码如下所示(为清楚起见,切掉了不相关的部分):

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

因此,用户按下按钮,脚本将加载发票页面,然后等待,每四分之一秒检查一次发票页面是否已完成加载,然后弹出打印对话框供用户将其发送到打印机。QED。


12
在考虑作者想要实现的简单事物时,似乎有非常可怕的解决方案。
xaralis

2
这取决于不推荐使用的Java Applets。
Vahid Amiri

6

许多答案没有(直接)回答这个问题,这个也没有。

这是我的两个美分(或功能):

如果您想要比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毫秒...”)


5

对于特定的情况,希望将一组由循环执行的调用隔开,可以将以下代码与原型一起使用。如果没有原型,则可以用setTimeout代替delay函数。

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

5

如果您使用的是node.js,可以看看光纤 –节点的本机C扩展,一种多线程模拟。

它允许您以sleep阻塞光纤中执行的方式执行操作,但不会在主线程和其他光纤中阻塞。

这是他们自述文件中的一个新示例:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

–结果是:

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
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.