我有一个带有回调函数的按钮。 我希望按钮在单击时启动 5 秒延迟的超时。 如果在 5 秒内再次单击该按钮,我希望重置超时而不调用超时处理程序。 然后当 5 秒过去时,处理程序被调用。
[timeoutHasInitiated, setTimeoutHasInitiated] = useState(false);
function callbackFunction() {
if (!timeoutHasInitiated) {
setTimeoutHasInitiated(true);
console.log('Button clicked: Timeout Started.');
const timeout = setTimeout(() => {
setTimeoutHasInitiated(false);
console.log('Timeout has Finished.');
}, 5000);
return () => clearTimeout(timeout);
}
else {
console.log('Button clicked while timeout in progress');
}
}
在上面的代码中,超时后单击按钮不会执行任何操作。
如果我尝试类似的事情:
function callbackFunction() {
clearTimeout(timeout);
const timeout = setTimeout(() => {
setTimeoutHasInitiated(false);
console.log('Timeout has Finished.');
}, 5000);
return () => clearTimeout(timeout);
}
我收到错误:
在声明之前使用块范围变量“timeout”。
变量“超时”在分配之前使用。
如果我尝试先声明超时,然后再将其分配给 setTimeout() ,如下所示:
function callbackFunction() {
let timeout;
clearTimeout(timeout);
timeout = setTimeout(() => {
setTimeoutHasInitiated(false);
console.log('Timeout has Finished.');
}, 5000);
return () => clearTimeout(timeout);
}
在 setTimeout() 之前调用的clearTimeout(timeout)似乎没有做任何事情,因为多次按下按钮会启动多个超时。
我想我可以在单击按钮后禁用该按钮作为解决方法,但我想知道是否有一种方法可以对我描述的所需行为进行编程。
如果您将
timeout
的声明移至 callbackFunction
之外,它应该按您的预期工作。
let timeout;
function callbackFunction() {
clearTimeout(timeout);
timeout = setTimeout(() => {
setTimeoutHasInitiated(false);
console.log('Timeout has Finished.');
}, 5000);
return () => clearTimeout(timeout);
}
对
callbackFunction
的每次调用都会创建一个新的执行上下文,因此当前每个调用都在访问其自己的本地作用域的 timeout
声明,这就是为什么您会看到多次按下按钮引发多个超时。 或者您可以使用 timeout
将 this.timeout
范围限定为函数,但由于是自学,我不确定这种方法的缺点。
function callbackFunction() {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
setTimeoutHasInitiated(false);
console.log('Timeout has Finished.');
}, 5000);
return () => clearTimeout(timeout);
}