wan*_*len 0 javascript time node.js
根据文档,setTimeout的实际延迟可能比要求的时间更长。您能指出文件或问题的答案吗,这可能解释setTimeout的实际延迟是否比要求的短?
我遇到的是很少发生的问题,可以用这种现象来解释。平台:Chrome版本67,NodeJS版本9.8.0。另外,我真的很好奇这句话对Firefox和其他浏览器是否正确?
您可以通过获取两个微时间的增量来测试超时或间隔准确性。在我的测试中,计时器为正负几毫秒。运行以下程序以在您自己的环境中查看结果。
在一个完美的世界中,输出将始终显示1000。输出的差异意味着我们的世界是不完美的
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 Code Online (Sandbox Code Playgroud)
要显着影响结果,请按运行,切换到另一个选项卡,然后在几秒钟后返回此选项卡。您会看到散焦的标签差异很大。
// 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
Run Code Online (Sandbox Code Playgroud)
我不了解影响JavaScript超时和间隔准确性的所有因素,但是我也不认为这是重要的事情。最终,我们不需要准确性,因为我们可以使用上述增量技术来计算精确的持续时间。
React中的一个实际例子
下面我们创建一个简单的Timer组件,它天真地用于setInterval每秒刷新一次计时器的显示...
// 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
Run Code Online (Sandbox Code Playgroud)
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')
)Run Code Online (Sandbox Code Playgroud)
但是由于JavaScript计时器的不可靠特性,我们知道我们的Timer组件最终将显示错误的值。
当我们实现PreciseTimer以下内容时,我们可以使用增量技术来确保组件始终显示正确的持续时间
<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>Run Code Online (Sandbox Code Playgroud)
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')
)Run Code Online (Sandbox Code Playgroud)
要查看这两个计时器在行为上的实际差异,请启动两个计时器,切换到新标签10-15秒钟,然后再切换回该标签。天真Timer会受到JavaScript计时器变化的影响,而PreciseTimer始终会显示正确的持续时间。