【问题标题】:How to make an accurate delay function in javascript如何在javascript中制作准确的延迟函数
【发布时间】:2021-07-26 22:07:36
【问题描述】:

我正在制作音乐作曲家并播放音符,我正在等待播放下一个音符之前的时间(以毫秒为单位),我发现这似乎非常不准确,有时高达 10 毫秒的不准确,有没有办法让我可以做出更准确的超时或延迟功能来降低 0/1 毫秒的差异? 我目前的代码是:

function delayMs(ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms)
    })
}

使用“tick”功能:

        while (this.state.isPlaying) {
            const { song, settings } = this.state
            let msPerBPM = Math.floor(60000 / settings.bpm.value)
            await delayMs(msPerBPM)
            this.handleTick()
        }

我可以使用服务人员,因为我注意到我遇到了这个问题,因为反应中的重新渲染延迟。

【问题讨论】:

  • 简而言之,没有。你永远不会在 javascript 中获得 setTimeout 的毫秒精度
  • 它总是在 timout 完成后进入队列,因此无法保证它会立即执行。对于工人来说,情况可能会更糟,也可能不会更糟,这取决于你到底在做什么。工作进程和主进程之间的通信开销很大。

标签: javascript reactjs time


【解决方案1】:

很容易证明使用setTimeout(以及扩展名setInterval)您永远无法获得毫秒精度。

下面演示了即使告诉 javascript 在 1 毫秒内执行,它也可以在几毫秒到几十毫秒后实际进行调用。

function recall(count){
  console.log(new Date())
  if(++count<10)
    setTimeout(recall,1,count);
}

recall(1)

requestAnimationFrame 可能会让您更幸运,但您需要再次计算自上一步以来经过了多长时间,并使用它来“同步”您想做的任何事情:

let start;

function step(timestamp) {
  if (start === undefined)
    start = timestamp;
  const elapsed = timestamp - start;

  console.log(elapsed);
  
  if (elapsed < 500) { // Stop the animation after 0.5 seconds
    window.requestAnimationFrame(step);
  }
}

window.requestAnimationFrame(step);

【讨论】:

  • 动画帧不够准确,30ms 的步长太高了,但我想我会尝试做一些“错误缓解”,消除与下一个超时的差异,前一个错误超时了
  • @Specy 是的,但是(不要引用我的话)我脑海中的某些东西认为动画帧比 setTimeout 更可预测
  • 嗯,是的,但是如果我有 40 毫秒的超时时间呢?它将每 2 帧运行一次,即 +-60 毫秒,+20 毫秒错误。
猜你喜欢
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多