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

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

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


当前回答

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

其他回答

要使主线程忙碌几毫秒,请执行以下操作:

function wait(ms) {
  const start = performance.now();
  while(performance.now() - start < ms);
}

一行使用Promise

const wait = t => new Promise(s => setTimeout(s, t, t));

带有中止信号的字体

const wait = (x: number, signal?: AbortSignal): Promise<number> => {
  return new Promise((s, f) => {
    const id = setTimeout(s, x, x);
    signal?.addEventListener('abort', () => {
      clearTimeout(id);
      f('AbortError');
    });
  });
};

Demo

const wait=t=>new Promise(s=>setTimeout(s,t));//用途异步函数demo(){//倒计时设i=6;而(i-){等待等待(1000);控制台日志(i);}//数字0到5的总和,延迟1秒constsum=await[…Array(6).keys()].reduce(async(a,b)=>{a=等待a;等待等待(1000);常量结果=a+b;console.log(`${a}+${b}=${result}`);返回结果;},承诺.决议(0));console.log(“sum”,总和);}demo();

这是一种阻塞型睡眠。发现在需要顺序执行的测试活动中更容易遵循。它可以被称为sleep(2000),让线程休眠2秒。

function sleep(ms) {
    const now = Date.now();
    const limit = now + ms;
    let execute = true;
    while (execute) {
        if (limit < Date.now()) {
            execute = false;
        }
    }
    return;
  }

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

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游戏中使用这个。

实际上,您可以使用与pausecomp函数相同的while循环实现sleep()(这基本上是相同的):

const sleep = (seconds) => {
    const waitUntil = new Date().getTime() + seconds * 1000
    while(new Date().getTime() < waitUntil) {
        // do nothing
    }
}

您可以像这样使用sleep()方法:

const main = () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    sleep(4)
    const c = b + 5
}

main()

这就是我想象你会使用睡眠功能的方式,而且读起来相对简单。我借鉴了另一篇文章《JavaScript中的睡眠——动作之间的延迟》,以展示您可能打算如何使用它。

不幸的是,你的电脑会变热,所有工作都会受阻。如果在浏览器中运行,该选项卡将停止,用户将无法与页面交互。

如果您将代码重组为异步的,那么您可以将setTimeout()作为与其他文章相同的睡眠函数。

// define sleep using setTimeout
const sleep = (seconds, callback) => setTimeout(() => callback(), seconds * 1000)

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    sleep(3, () => {
        b = a + 4

        // Sleep 4 seconds before the next action
        sleep(4, () => {
            c = b + 5
        })
    })
}

main()

正如你所说,这不是你想要的。我修改了Sleep in JavaScript中的示例-动作之间的延迟,以说明为什么会出现这种情况。当您添加更多动作时,要么需要将逻辑拉入单独的函数,要么将代码嵌套得越来越深(回调地狱)。

为了解决“回调地狱”,我们可以使用promise来定义睡眠:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    return sleep(3)
        .then(() => {
            b = a + 4

            // Sleep 4 seconds before the next action
            return sleep(4)
        })
        .then(() => {
            c = b + 5
        })
}

main()

Promise可以避免深度嵌套,但看起来仍然不像我们最初使用的常规同步代码。我们希望编写看起来同步的代码,但没有任何缺点。

让我们再次使用async/await重写我们的主方法:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = async () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    await sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    await sleep(4)
    const c = b + 5
}

main()

使用async/await,我们可以调用sleep(),就好像它是一个同步的阻塞函数一样。这解决了您可能在其他帖子中使用回调解决方案时遇到的问题,并避免了长时间循环的问题。