【问题标题】:Sleep main thread but do not block callbacks休眠主线程但不阻塞回调
【发布时间】:2026-01-30 05:40:01
【问题描述】:

此代码有效,因为system-sleep 阻止了主线程的执行,但不阻止回调。但是,我担心 system-sleep 不是 100% 可移植的,因为它依赖于依赖 C++ 的 deasync npm 模块。

是否有任何替代系统睡眠的方法?

var sleep = require('system-sleep')
var done = false

setTimeout(function() {
  done = true
}, 1000)

while (!done) {
  sleep(100) // without this line the while loop causes problems because it is a spin wait
  console.log('sleeping')
}

console.log('If this is displayed then it works!')

PS 理想情况下,我想要一个适用于 Node 4+ 的解决方案,但有总比没有好。

PPS 我知道睡觉不是最佳做法,但我不在乎。我厌倦了反对睡觉的争论。

【问题讨论】:

  • 哦,总而言之,只有主线程运行回调/事件,所以如果你阻塞主线程(node.js 只在主线程中运行 Javascript),来自事件队列的回调也会被阻塞。你无法改变这一点。因此,您的标题所要求的根本不是您在 node.js 中可以做到的。
  • @jfriend00 如果它在节点中不可能,那么为什么我在问题中给出的代码有效?请正确阅读。我知道如何使用承诺和回调。由于我自己的原因,我不想在这里使用它们。此外,我使用的是 Node 4,因此我无法使用 async/await。
  • 进一步研究表明,deasync 是另一个项目的分支。另一个项目警告不要使用它,因为它只是一个 hack。由于系统睡眠依赖于异步,我也不会使用它。
  • 好吧,deasyncsleep() 依赖于此)使用了相当多的技巧。它是一个本机代码 node.js 插件,可以从 C++ 代码手动运行事件循环,以完成它正在做的事情。只有真正了解 node.js 内部(现在和将来)的人才能想象这样做的问题所在。如果不破解 node.js 本机代码,您所要求的内容在常规​​ Javascript 代码中是不可能的,因为它与 Javascript 设计为在 node.js 中运行的方式完全相反。这就是我想与您交流的内容。
  • 所有 Babel 对 async/await 所做的只是为你编写常规的promise.then() 代码。 async/await 是语法便利。他们并没有真正做任何你不能用 Promise、.then().catch() 和在某些情况下 Promise.all() 编写的事情。所以,再一次,我真的不明白你想要完成什么。是的,如果您想为节点 4 编写 async/await 样式代码,那么您可以使用 Babel 将您的代码转换为将在节点 4 上运行的东西。没有任何非同步解决方案不是对引擎的破解,因为引擎的设计初衷不是做 deasync 所做的事情。

标签: node.js node-deasync


【解决方案1】:

根据您的要求将我的 cmets 收集到一个答案中:

好吧,deasyncsleep() 取决于)使用了相当多的技巧。它是一个本机代码 node.js 插件,可以从 C++ 代码手动运行事件循环,以完成它正在做的事情。只有真正了解 node.js 内部(现在和将来)的人才能想象这样做的问题所在。如果不破解 node.js 本机代码,您所要求的内容在常规​​ Javascript 代码中是不可能的,因为它与 Javascript 设计为在 node.js 中运行的方式完全相反。

了解并感谢。我正在尝试编写一个不使用 hack 的更可靠的 deasync(在某些平台上失败)模块。显然,我给出的这种方法不是答案。我希望它支持节点 4。我现在正在考虑将 yield / async 与 babel 结合使用,但我不确定这也是我所追求的。我需要一些东西,它会等到回调被解决,然后从异步回调中返回值。

Babel 对async/await 所做的所有事情都是为您编写常规的promise.then() 代码。 async/await 是语法便利。他们并没有真正做任何你不能用 Promise、.then().catch() 和在某些情况下 Promise.all() 编写的事情。所以,是的,如果您想为节点 4 编写 async/await 样式代码,那么您可以使用 Babel 将您的代码转换为将在节点 4 上运行的代码。您可以在使用 async/await 时查看转换后的 Babel 代码和您只会找到常规的promise.then() 代码。

没有任何deasync 解决方案不是对引擎的破解,因为引擎的设计初衷不是为了执行 deasync 的功能。

node.js 中的 Javascript 旨在一次运行一个 Javascript 事件,并且该代码一直运行,直到将控制权返回给系统,然后系统将从事件队列中提取下一个事件并运行其回调。您的 Javascript 是单线程的,设计上没有先发制人的中断。 如果没有对 JS 引擎进行某种破解,您就无法暂停或休眠一段 Javascript,然后再运行其他事件。它根本不是为了做到这一点而设计的。

【讨论】:

  • 非常感谢您的解释。我会放弃我的尝试:)
【解决方案2】:
var one = 0;

function delay(){
 return new Promise((resolve, reject) => {
   setTimeout(function(){
     resolve('resolved')
   }, 2000);
 })
}


while (one == 0) {
  one = 1;
  async function f1(){
    var x = await delay();
    if(x == 'resolved'){
      x = '';
      one = 0;
      console.log('resolved');
      //all other handlers go here... 
      //all of the program that you want to be affected by sleep()
      f1();
    }
  }
  f1();
}

【讨论】:

  • 感谢您的回复。节点 4 上是否可以使用异步?是es7吗?无论哪种方式,我都感谢您的回复,但理想情况下我正在寻找在节点 4 上运行的东西。+1
  • 没问题,我不知道,我不这么认为。试一试。如果它不起作用,请尝试使用 node --harmony-async-await app.js @danday74 运行您的应用