有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?

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

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


当前回答

对于希望将循环执行的一组调用隔开的特定情况,可以使用类似于下面代码的原型。如果没有原型,可以用setTimeout替换延迟函数。

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

其他回答

JavaScript是一个单线程执行环境。每个函数都只由一个线程执行。请求“休眠”意味着你想让整个VM实例停止那么多(毫秒),我认为这在JavaScript世界中不是一个非常现实的要求,因为如果执行线程休眠,那么不仅是特定的函数,所有其他执行都会受到影响。

首先,不可能真正休眠该线程。你只能通过不做任何事情的方式来让线程保持忙碌。但是,如果您只想在某些计算中添加延迟,请将它们的执行放在单个函数上下文中,并让继续发生在该函数中的setTimeout(或Promise,如果您愿意)中。如果通过睡眠,你想要延迟一些事情,否则,这是不可能的。

总结一下(就像前面的回答中所说的):

JavaScript中没有内置的睡眠函数。您应该使用setTimeout或setInterval来实现类似的效果。

如果你真的想,你可以用一个for循环来模拟睡眠功能,比如原始问题中所示的循环,但这会让你的CPU工作得很疯狂。在Web Worker内部,另一种解决方案是向非响应IP地址发出同步XMLHttpRequest,并设置适当的超时。这将避免CPU利用率问题。下面是一个代码示例:

//仅在web工作程序内部工作函数休眠(毫秒){var req=新XMLHttpRequest();请求打开(“GET”,“http://192.0.2.0/“,错误);req.timeout=毫秒;尝试{请求发送();}捕获(ex){}}console.log('休眠1秒…');睡眠(1000);console.log(“睡眠!”);console.log('休眠5秒…')睡眠(5000);console.log(“睡眠!”);

这可以使用Java的睡眠方法来完成。我已经在Firefox和Internet Explorer中测试过它,它不会锁定计算机,不会占用资源,也不会导致无休止的服务器攻击。对我来说,这似乎是一个干净的解决方案。

首先,您必须在页面上加载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" />

然后,当您想要在JavaScript代码中轻松暂停时,您需要做的就是:

java.lang.Thread.sleep(xxx)

其中xxx是以毫秒为单位的时间。在我的案例中(作为理由),这是一家非常小的公司后端订单履行的一部分,我需要打印一张必须从服务器加载的发票。我是通过将发票(作为网页)加载到iFrame中,然后打印iFrame来完成的。

当然,我必须等到页面完全加载后才能打印,所以JavaScript代码必须暂停。我通过让发票页面(在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。

我在JavaScript sleep/wait上搜索了很多网页。。。如果你想让JavaScript“RUN,DELAY,RUN”。。。大多数人得到的要么是“RUN,RUN(无用的东西),RUN”,要么是“RUN,RUN+延迟RUN”。。。

我想:这是一个有效的解决方案。。。但你必须把你的跑步代码切碎…:是的,我知道,这只是一个更容易理解的重构。。。还

示例1:

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

示例2:

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

示例3:

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

示例4:

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

如果您使用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');