在Node.js中睡觉

lor*_*isi 0 javascript multithreading sleep node.js

假设没有"原生"方式来实现这一点,我的解决方案就像

sleep = function(time) {
        var stop = new Date().getTime();
        while(new Date().getTime() < stop + time) {
            ;
        }
        return new Promise((r,_)=> r())
      }
Run Code Online (Sandbox Code Playgroud)

这样做sleep(1000*3).then(()=>console.log("awake"))会睡3秒,然后解决Promise:

(请注意,它会冻结此页面一秒钟.)

sleep = function(time) {
  var stop = new Date().getTime();
  while (new Date().getTime() < stop + time) {;
  }
  return new Promise((r, _) => r())
}
console.log("sleeping...")
sleep(1000 * 1).then(() => console.log("awake"))
Run Code Online (Sandbox Code Playgroud)

假设这将在主线程中运行,它将冻结主进程以便这样做

sleep(1000*1).then(()=>console.log("awake")); console.log("Hello")
Run Code Online (Sandbox Code Playgroud)

它会产生一个输出

VM2628:1 Hello
VM2628:1 awake
Run Code Online (Sandbox Code Playgroud)

在睡眠结束时.当然在做

setTimeout(()=>sleep(1000*3).then(()=>console.log("awake")),1000);console.log("Hello")
VM2815:1 Hello
undefined
VM2815:1 awake
Run Code Online (Sandbox Code Playgroud)

将使它异步,但它不能满足我的需要(放到sleep我的主要过程).有更好的方法吗?

Jon*_*lms 6

根本不需要冻结.由于javascripts异步性,我们可以将代码的一部分留下一段时间并稍后恢复.首先,我们需要一个有希望的计时器

 const timer = ms => new Promise( res => setTimeout(res, ms));
Run Code Online (Sandbox Code Playgroud)

然后我们可以简单地使用它:

console.log("wait 3 seconds")
timer(3000).then(_=>console.log("done"));
Run Code Online (Sandbox Code Playgroud)

或者有点语法糖:

(async function(){
  console.log("wait 3 seconds");
  await timer(3000);
  console.log("done");
})()
Run Code Online (Sandbox Code Playgroud)

如果你真的想要冻结(非常糟糕),你根本不需要承诺:

function freeze(time) {
    const stop = new Date().getTime() + time;
    while(new Date().getTime() < stop);       
}

console.log("freeze 3s");
freeze(3000);
console.log("done");
Run Code Online (Sandbox Code Playgroud)


小智 6

从 Node v15.0.0 开始,节点内置了一个基于 Promise 的“睡眠”函数

您可以使用Timers Promises API来睡眠。

import {setTimeout} from 'timers/promises';

await setTimeout(100);
Run Code Online (Sandbox Code Playgroud)

如果您想使用旧的基于回调的方法setTimeout()- 或者就像名称一样sleep()- 您可以为 Promise 计时器起别名。

import {setTimeout as sleep} from 'timers/promises';

// promise `setTimeout` aliased as `sleep`
await sleep(100);
console.log('I waited'));

// regular callback `setTimeout` (scheduling timers)
setTimeout(() => console.log('I also waited'), 100);
Run Code Online (Sandbox Code Playgroud)