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

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

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


当前回答

等待支持和蓝鸟承诺:

await bluebird.delay(1000);

这将像C语言的同步休眠(1)一样工作。我最喜欢的解决方案。

其他回答

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

为了测试,我需要一段忙碌的等待。我不想拆分代码,因为这需要很多工作,所以一个简单的for为我做了这件事。

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

我看不出这样做有什么坏处,这对我来说很有好处。

首先,应该使用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调用,超时设置为睡眠值。这就是真正睡觉的唯一方法。

我认为这个问题很好,指出了重要的观点和考虑因素。

话虽如此,我认为问题的核心在于意图和理解开发人员(您)想要控制什么。

首先,名称sleep是一个重载的命名选择。即,“什么”将被“睡眠”;作为一名开发人员,我控制着什么?

在任何语言引擎中,在任何OS进程上运行,在任何裸机或托管系统上,“开发人员”都不控制(拥有)OS共享资源CPU内核(和/或线程),除非他们正在编写OS/process系统本身。CPU是一种时间共享资源,工作执行进度的货币是分配给系统上要执行的所有工作的“周期”。

作为一名应用程序/服务开发人员,最好考虑我是由操作系统进程/语言引擎管理的工作流活动流的控制者。在一些系统上,这意味着我控制一个本机os线程(可能共享CPU内核),在其他系统上,意味着我可以控制一个异步延续工作流链/树。

对于JavaScript,它是“后者”。

因此,当需要“睡眠”时,我打算让我的工作流在执行过程中“延迟”一段时间,然后再继续执行工作流中的下一个“步骤”(阶段/活动/任务)。

这是“恰当”的说法,即作为一个开发人员,最容易将模型作为线性代码流来工作;根据需要采用工作流的组合来进行缩放。

今天,在JavaScript中,我们可以选择使用高效的多任务20世纪80年代基于角色的延续架构(重新标记为现代Futures/Promises/then/await等)来设计这样的线性工作流。

考虑到这一点,我的答案不是提供新的技术解决方案,而是关注问题本身的意图和设计视角。

我建议,任何答案都要从思考上述概念开始,然后选择一个提醒和暗示意图的名字(而不是睡眠)。

工作流选择1:delayWorkForMs(nMsToDelay)选项2:delaySyncSequenceForMs(msPeriod)

async delayAsyncSequenceForMs(msPeriod) {
  await new Promise(resolve => setTimeout(resolve, msPeriod));
}

请记住,任何异步函数都会返回Promise,await只能在异步函数中使用。(哈哈,你可能会问自己为什么……)。注意事项1:不要使用“循环”来消耗cpu周期。注意事项2:在JavaScript模型中,当在非异步函数中时,您不能“延迟”(等待)“异步”工作流的执行(除非您正在做不必要的坏事,而不需要占用cpu周期)。您只能在“异步”函数中“延迟”代码步骤。在内部,“异步”函数被建模为每个await关键字处的入口点/延续的集合。如果您熟悉倒勾插值模型,您可以“将await”视为在概念上建模,类似于编写倒勾字符串,如:

  // Conceptualizing, using an interpolation example to illustrate
  // how to think about "await" and "async" functions
  `code${await then-restart-point}more-code${await then-restart-point}`

内联函数:

(async () => await new Promise(resolve => setTimeout(resolve, 500)))();

500是VM在移动到下一行代码之前等待的时间(以毫秒为单位)。

tldr位;

基本上,当您创建一个promise时,它会在创建时返回一个可观察到的值,在回调中提供一个解析引用,用于在数据/响应可用时移交数据/响应。在这里,在500ms后通过setTimeOut调用resolve,直到未执行resolve之前,外部作用域正在等待进一步的处理,因此,创建了一个伪块。这与非阻塞(或调用其他语言中可用的非线程保留睡眠)完全不同,因为线程和最可能的UI以及网页/节点应用程序的任何其他正在进行的任务将被阻塞,而主线程将专门用于等待承诺解决。