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

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

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


当前回答

如果确实要暂停脚本,可以执行以下操作:

var milliseconds;
var pretime;
var stage;

function step(time){
  switch(stage){
    case 0:
      //Code before the pause

      pretime=time;
      milliseconds=XXX;
      stage=1;
      break;
    case 1:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=2;
      }
      break;
    case 2:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=3;
      }
      break;
    case 3:
      //Etc...
  }

  Window.requestAnimationFrame(step)
}

step();

如果您使用循环,这可能正是您想要的,并且您可以以某种方式对其进行更改,从而获得伪多线程,其中一些函数等待一段时间,其他函数正常运行。我一直在纯JavaScript游戏中使用这个。

其他回答

一个用于休眠的函数,使用同步调用让操作系统执行。使用您喜欢的任何操作系统休眠命令。在使用CPU时间的意义上,它并不忙着等待。

我在一个不存在的地址上选择了ping。

const cp = require('child_process');

function sleep(ms)
{
    try{cp.execSync('ping 192.0.2.0 -n 1 -w '+ms);}
    catch(err){}
}

测试以验证其是否有效

console.log(Date.now());
console.log(Date.now());
sleep(10000);
console.log(Date.now());
console.log(Date.now());

以及一些测试结果。

1491575275136
1491575275157

(10秒后)

1491575285075
1491575285076

第一:

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

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

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

setTimeout(alertWorld, 1000)

注意两件事

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

对于浏览器,我同意使用setTimeout和setInterval。

但是对于服务器端代码,它可能需要一个阻塞函数(例如,这样可以有效地进行线程同步)。

如果您正在使用Node.js和Meteor,您可能遇到了在光纤中使用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');

参见:Node.js光纤,睡眠

这可以使用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。

我知道这个问题是关于睡眠的,显然答案是不可能的。我认为睡眠的一个常见需求是按顺序处理异步任务;我知道我肯定要处理它。

在许多情况下,它可以使用promise(Ajax请求通用)。它们允许您以同步方式进行异步操作。还有成功/失败的处理,它们可以被链接起来。

它们是ECMAScript 6的一部分,所以浏览器支持还不完全,主要是Internet Explorer不支持它们。还有一个名为Q的库,用于实现承诺。

参考文献:

JavaScript承诺:简介ES6 Promise:ES6风格Promise的polyfill(Shim适用于旧版浏览器或Internet Explorer浏览器)