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

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

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


当前回答

如果您真的需要等待那么多秒,那么当前接受的使用async/await和setTimeout的解决方案是完美的。然而,如果您将其用于屏幕动画,则应该真正使用requestAnimationFrame()。此函数的功能与setTimeout非常相似,但回调仅在用户可见动画时调用。这意味着,如果您在网站上运行动画,并且用户切换选项卡,动画将暂停并节省电池寿命。

这里是使用requestAnimationFrame的wait方法的实现。它接收多个帧,并在它们全部通过后解析:

常量动画等待=(帧)=>新承诺((决心)=>{让framesPassed=0;requestAnimationFrame(函数循环(){如果(++framesPassed>=帧)返回resolve();requestAnimationFrame(循环);});});//演示用打字机效果const content=document.querySelector(“.content”);异步函数类型Writer(endText,等待){content.textContent=“”;for(const letter of endText){content.textContent+=字母;wait animationWait(等待);}}typeWriter(“好的。这个简单的打字机效果是requestAnimationFrame的一个例子。”,8);<p>动画将在下面播放;尝试切换选项卡并查看动画暂停。</p><code class=“content”></code>

阅读有关requestAnimationFrame的更多信息

浏览器支持(IE10+)

其他回答

这里有一种在.hta脚本中休眠的方法,这样当脚本唤醒时,它会按顺序执行下一个命令,这在循环中是必要的。这是一个真正的睡眠;它不会在睡眠期间保持处理器忙碌。例如,处理器能够在睡眠期间下载和呈现页面。

就一次,在代码开始时,开始

var WSHShell = new ActiveXObject ("WScript.Shell");

对于例如1秒=1000毫秒的休眠,执行以下语句

WSHShell.Run('Sleep.js 1000', 3, true);

与脚本相同的目录中有文件Sleep.js,其中包含以下一行:

WScript.Sleep(WScript.Arguments (0));

(注意;0在括号中,而不是括号中。)后者是实际执行睡眠的行。前面代码段中的参数true使调用同步。前一个参数中的3似乎没有任何效果,但你需要一些参数,以便true是第三个参数。

微软说“WScript对象……在调用其财产和方法之前,永远不需要实例化,并且它总是可以从任何脚本文件中使用。”但事实并非如此。它可以在一个独立的.js文件中使用,如上面所述,但显然不能在.hta文件使用的.js中使用,所以它必须在一个单独的文件中,如上所述调用。

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

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

这可能是最接近你想要的东西。

注意,如果你需要多次睡眠,这可能会在匆忙中变得很难看,你可能需要重新考虑你的设计。

首先,应该使用setTimeout和setInterval,因为JavaScript具有回调性质。如果您想使用sleep(),则是控制流或代码架构不正确。

尽管如此,我想我仍然可以帮助实现两个睡眠。

1.我头顶上的假同步跑步:

// A module to do that //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
var _ = (function(){
  var queue = [];
  var play = function(){
    var go = queue.shift();
      if(go) {
        if(go.a) {
          go.f();
          play();
        }
        else
        {
          setTimeout(play, go.t);
        }
      }
  }
  return {
    go:function(f){
      queue.push({a:1, f:f});
    },
    sleep:function(t){
      queue.push({a:0, t:t});
    },
    playback:play
  }
})();

[也可以自动播放]

// Usage

_.go(function(){

  // Your code
  console.log('first');

});

_.sleep(5000);

_.go(function(){

  // Your code
  console.log('next');

});

// This triggers the simulation
_.playback();

2.实际同步运行

有一天,我对它进行了很多思考,我在JavaScript中真正睡觉的唯一想法就是技术。

睡眠函数必须是同步Ajax调用,超时设置为睡眠值。这就是真正睡觉的唯一方法。

如果你写一个这样的睡眠函数

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

你有一个异步函数可以多次调用,

var xhr = function(url, callback){
    // Make an Ajax request
    // Call a callback when the request fulfils
}

您的项目设置如下:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});
}
function xhr2(){
    xhr(url2, function(){ ready = true; });
}
function xhr3(){
    xhr(url3, function(){ ready = true; });
}

然后您可以执行以下操作:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // Do more
});

而不是像这样无休止的回调缩进:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // Do more
        });
    });
});

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

每次我想在函数中间休眠时,我都会重构以使用setTimeout()。

Edit

任何语言中臭名昭著的睡眠或延迟功能都备受争议。有些人会说,应该总是有一个信号或回调来启动给定的功能,而另一些人会认为,有时任意的延迟时间是有用的。我说,每个人都有自己的规则,在这个行业中,一条规则永远无法支配任何事情。

编写睡眠函数很简单,而且使用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!
});