允许在nodejs中每毫秒运行一次setInterval

For*_*vin 19 javascript loops setinterval node.js

我有一个节点脚本,它应该利用单个节点进程可以获得的所有CPU资源.但我发现setInterval太慢了.

当然,我在文档中发现了这一点:

当延迟大于2147483647或小于1时,延迟将设置为1.

来源:https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args

现在我想知道是否有办法进一步减少限制,或者是否有可以使用的替代功能.

我不能只使用普通循环,因为还有其他需要同时运行的异步事件.

编辑:
再次:我不能只使用普通循环,因为还有其他需要同时运行的异步事件.我不确定为什么这么难理解.

正常循环正在运行时,您将阻止其他所有操作的执行.如果将循环放在另一个异步执行的函数中并不重要.

这是什么意思?

我们来看一些例子:

setInterval(()=>{console.log('a')},1000) // asynchronous thing that needs to run in the background

while (true) {
    // do whatever
}
Run Code Online (Sandbox Code Playgroud)

这段代码会做什么?它会阻止一切.console.log('a')不会连续执行.

setInterval(()=>{console.log('a')},1000) // asynchronous thing that needs to run in the background
setTimeout(()=>{
    while (true) {
        // do whatever
    }
}, 1)
Run Code Online (Sandbox Code Playgroud)

一旦while循环开始,这也将阻止间隔的执行.

The*_*son 8

我相信这个问题属于节点而不是浏览器.您可以使用以下某些选项(递归/循环)来减少延迟时间.

setImmediate

setImmediate - 在I/O事件的回调之后安排"立即"执行回调.返回立即与clearImmediate()一起使用.

当对setImmediate()进行多次调用时,回调函数将按照创建它们的顺序排队等待执行.每次事件循环迭代都会处理整个回调队列.如果立即计时器从执行的回调内部排队,则在下一个事件循环迭代之前不会触发该计时器.

这是来自node导游:

setImmediate并且setTimeout是相似的,但根据它们被调用的时间以不同的方式表现.

  • setImmediate() 设计用于在当前轮询阶段完成后执行脚本.
  • setTimeout()安排在经过最小阈值(ms)后运行的脚本.

process.nextTick

process.nextTick()方法将回调添加到"下一个滴答队列".一旦事件循环的当前转弯转到完成,将调用当前在下一个滴答队列中的所有回调.

node指南

我们建议开发人员在所有情况下都使用setImmediate(),因为它更容易推理(并且它导致代码与更广泛的环境兼容,如浏览器JS.)


For*_*vin 5

感谢乔什·林(Josh Lin)提出的运行多个间歇训练的想法。我最终得到了setInterval和的两个简单的包装函数clearInterval

function setInterval2(cb,delay) {
    if (delay >= 1)
        return [setInterval(cb,delay)];
    var intervalArr = [];
    var intervalCount = Math.round(1/delay);
    for (var i=0; i<intervalCount; i++)
        intervalArr.push(setInterval(cb,1));
    return intervalArr
}

function clearInterval2(intervalArr) {
    intervalArr.forEach(clearInterval);
}
Run Code Online (Sandbox Code Playgroud)

它的工作原理就像原来的函数一样:

var count = 0;

// run interval every 0.01 milliseconds:
var foo = setInterval2(function(){
    count++;
},0.01);

// stop execution:
clearInterval2(foo)
Run Code Online (Sandbox Code Playgroud)


Jos*_*Lin 4

1setInterval跑几次!

let count = 0,
  by = 100,
  _intervals = [],
  timelimit = 100
for (let i = 0; i < by; i++) {
  _intervals[i] = setInterval(() => count++, 1)
}
setTimeout(() => {
  _intervals.forEach(x => clearInterval(x))
  console.log(`count:${count}`)
}, timelimit)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

2.减少setTimeout递归运行!

let count = 0,
  go = true
recurser()
setTimeout(() => {
  go = false
  console.log(`count:${count}`)
}, 100)

function recurser() {
  count++
  go && setTimeout(recurser)
}
Run Code Online (Sandbox Code Playgroud)
在此输入图像描述

3.requestAnimationFrame少跑!

let count = 0,
  go = true,
  timelimit = 100
step()
setTimeout(() => {
  go = false,
    console.log(`count:${count}`)
}, timelimit)

function step() {
  count++
  go && requestAnimationFrame(step)
}
Run Code Online (Sandbox Code Playgroud)
在此输入图像描述

据我所知,运行setInterval多次,我相信while会更重要