首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >setTimeout的实际延迟可能会更短吗?

setTimeout的实际延迟可能会更短吗?
EN

Stack Overflow用户
提问于 2018-06-18 22:33:23
回答 4查看 629关注 0票数 1

根据documentation的说法,setTimeout的实际延迟可能比所要求的更长。您能否在文档或问答中说明setTimeout的实际延迟是否会比所要求的更短?

问题是我遇到了一个很少发生的问题,可以用这样的现象来解释。平台: Chrome版本67,NodeJS版本9.8.0。另外,我真的很好奇,这句话对Firefox和其他浏览器来说是真的吗?

EN

回答 4

Stack Overflow用户

发布于 2018-06-18 22:42:49

您可以通过获取两个微秒的增量来测试超时或间隔准确性。在我的测试中,计时器是正负几毫秒。运行下面的程序,在您自己的环境中查看结果。

在理想情况下,输出总是显示1000。输出中的差异意味着我们的世界是不完美的

代码语言:javascript
运行
复制
var last = Date.now()
var interval = setInterval(function() {
  var now = Date.now()
  var delta = now - last
  console.log(delta)
  last = now
}, 1000)

setTimeout(clearInterval, 10000, interval)
// 1000
// 1003
// 998
// 1002
// 999
// 1007
// 1001
// ... 

要显著影响结果,请按Run,切换到另一个选项卡,然后在几秒钟后返回到此选项卡。您将看到分散的选项卡具有极高的方差。

代码语言:javascript
运行
复制
// 1004  <-- start experiment
// 997
// 1000  <-- switch to another tab
// 1533  <-- variance spikes immediately
// 866
// 1033
// 568   <-- switch back to this tab
// 1001  <-- variance restabilizes
// 1000
// 999

我不知道影响JavaScript中超时和时间间隔准确性的所有因素,但我也不认为这是一件需要了解的重要事情。最终,我们不需要精度,因为我们可以使用上面的增量技术来计算精确的持续时间。

在React中的一个实用示例

下面我们创建一个简单的Timer组件,它简单地使用setInterval每秒刷新一次计时器的显示。

代码语言:javascript
运行
复制
class Timer extends React.Component {
  constructor (props) {
    super (props)
    this.state = { seconds: 0, timeout: null }
  }

  componentDidMount () {
    this.setState ({
      timeout: setInterval (this.tick.bind(this), 1000)
    })
  }
  
  componentWillUnmount () {
    clearTimeout (this.timeout)
  }
  
  tick () {
    this.setState ({ seconds: this.state.seconds + 1 })
  }
  
  render () {
    return <div>Naive timer: {this.state.seconds}</div>
  }
}

ReactDOM.render
  ( <Timer />
  , document.getElementById ('timer')
  )
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="timer"></div>

但是由于JavaScript计时器的不可靠特性,我们知道我们的计时器组件最终会显示不正确的值。

当我们实现下面的PreciseTimer时,我们可以使用增量技术来确保组件始终显示正确的持续时间

代码语言:javascript
运行
复制
class PreciseTimer extends React.Component {
  constructor (props) {
    super (props)
    this.state = { start: Date.now (), seconds: 0, timeout: null }
  }

  componentDidMount () {
    this.setState ({
      timeout: setInterval (this.tick.bind(this), 1000)
    })
  }
  
  componentWillUnmount () {
    clearTimeout (this.timeout)
  }
  
  tick () {
    const delta = Date.now () - this.state.start
    this.setState ({ seconds: delta / 1000 })
  }
  
  render () {
    return <div>Precise timer: {this.state.seconds}</div>
  }
}

ReactDOM.render
  ( <PreciseTimer />
  , document.getElementById ('timer')
  )
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="timer"></div>

要查看这两个计时器行为的实际差异,请启动这两个计时器,切换到新选项卡10-15秒,然后切换回此选项卡。朴素的Timer将受到JavaScript计时器变化的影响,而PreciseTimer将始终显示正确的持续时间。

票数 6
EN

Stack Overflow用户

发布于 2018-06-18 22:43:12

实际上,在指定的延迟之后,setTimeout只会将回调推到事件循环的顶部,但是因为Javascript是单进程的,如果有什么东西阻塞了事件循环,回调就会被延迟。但它不能更短,或者是使用的代码/ javascript引擎中的错误。

票数 1
EN

Stack Overflow用户

发布于 2018-06-18 22:44:26

Javascript的单一执行线程意味着,有时您排队等待将来在点x执行的东西,实际上可能会在时间x+上执行,因为可能没有可用的执行时间范围。然而,在所需的时间之前,程序永远不能执行,只能在给定的时间内或之后执行。

例如,一个setTimeout(myFunc, 100 )可以在100ms后执行,或者更长一点。您可以在本文中找到更多关于javascrip计时器的一般信息:https://johnresig.com/blog/how-javascript-timers-work/

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50911839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档