单击开始按钮时,它将启动两个计数器。一个使用递归,另一个使用for循环。为什么循环计数器会阻止递归计数器的计数?另外,为什么for循环中的迭代次数有限制?
import React from 'react'
export default class Clock extends React.Component {
state = {
recursiveCount: 0,
loopCount: 0,
stop: false
}
clickStart = () => {
this.setState({
stop: false
}, () => {
this.startRecursion()
this.startLooping()
})
}
startLooping = () => {
for (let i = 0; i < 1000; i++) {
setTimeout(() => {
this.setState({
loopCount: this.state.loopCount + 1
})
}, 1)
}
}
stop = () => {
this.setState({
stop: true
})
}
startRecursion = () => {
if (!this.state.stop) {
setTimeout(() => {
this.setState({
recursiveCount: this.state.recursiveCount + 1
}, () => {
this.startRecursion()
})
}, 1)
}
}
render () {
return (
<div>
<button className = 'button' onClick =
{this.clickStart}>Start</button>
<button className = 'button' id = 'stop' onClick =
{this.stop}>Stop</button>
<h1>The recursive function has been recursively called {this.state.recursiveCount} times</h1>
<h1> The iterative function has been iteratively called {this.state.loopCount} times </h1>
</div>
)
}
}
答案 0 :(得分:3)
让我们逐步完成代码:
for (let i = 0; i < 1000; i++) {
它循环1000次。多数民众赞成,并且可能会挂起浏览器一段时间。
setTimeout(/*callback*/, 1);
您向队列添加了很多超时。现在代码已完成。一秒之后,所有超时同时触发,并且将直接一个接一个地执行。这就是为什么计数器直接从1000跳到2000的原因。
为什么循环计数器会阻止递归计数器的计数?
因为只有一个线程,而该线程将被全部同时进入线程队列的1000个回调阻止。递归超时也将在队列中结束,因此它将仅在其他1000个之后执行,这需要时间。
还有,为什么for循环中的迭代次数有限制?
循环中没有任何限制,但是,如果阻塞线程时间太长,它将崩溃以帮助客户端:
while(true );
另外,如chris所指出的那样,在循环中频繁调用setState
可能会给您带来麻烦。
答案 1 :(得分:0)
我不认为你想要
for (let i = 0; i < 1000; i++) {
setTimeout(() => {
this.setState({
loopCount: this.state.loopCount + 1
})
}, 1)
}
,因为它会排队1000个超时,而无需等待上一个超时完成。而且,是阻止。
这是一个工作代码框,其中包含我想要的内容:https://codesandbox.io/s/2xy00529jp
我采取了一些不同的方法-我一直在跟踪超时并在stop
上清除它们-我认为使用标志不会出现错误 (this.state.stop
),但我发现自己的方法更简洁。另外,我正在使用this.setState
的回调函数-在进行大量顺序状态更新时,新状态值依赖于先前的状态值,这非常重要。浏览this page,了解更多信息。