最佳方式处理取消 JavaScript 函数执行
Best way Handle cancellation of JavaScript function execution
我有三个功能:
let timeVar;
let savedFunctionCode;
function startTimer(code) {
savedFunctionCode = code;
timeVar = setTimeout(savedFunctionCode, 2000);
}
function resumeTimer(intervalTime = 2000) {
setTimeout(savedFunctionCode, intervalTime);
}
function stopTimer() {
clearTimeout(timeVar);
}
这样做的唯一目的基本上是一种暂停和恢复特定代码的方法。
现在在定时器被实例化后(通过调用 startTimer)可以暂停或恢复代码。
如果方法 stopTimer() 和 resumeTimer() 的调用间隔至少两秒,则暂停和恢复代码执行的预期行为有效。
但是,如果按照该顺序调用 resumeTimer() 和 stopTimer() 的时间少于两秒,stopTimer() 将不会成功 stop/pause resumeTimer() 预期执行。
我的理论:
在暂停状态下,调用 resumeTimer 时,代码会在两秒内执行。但是,如果您快速执行 stopTimer() ,则基本上没有什么可以停止的,因为 resumeTimer 的代码执行尚未开始。 (不到两秒)。
因此在两秒内 resumeTimer() 方法执行其代码,因为 stopTimer() 不会影响它。
问题: JavaScript 有没有办法让我执行 stopTimer() 时它会取消所有挂起的代码执行。所以在这种情况下,我希望 stopTimer() 取消将在 2 秒内发生的 resumeTimer() 代码执行。
如有不明白请指出。
示例:
<html>
<body>
<div id="media-holder">
<span id="play-button" onclick="resumeTimer();"></span>
<span id="pause-button" onclick="stopTimer();"></span>
</div>
<script>
let timeVar = setTimeout(execute, 2000);
function resumeTimer(intervalTime = 2000) {
setTimeout(execute, intervalTime);
}
function stopTimer() {
clearTimeout(timeVar);
}
function foo() {
for(let i = 0; i < 100; i++) {
console.log("execute");
}
}
</script>
<html>
如果你快速点击播放按钮和暂停按钮,它仍然会继续执行foo()方法,
JavaScript 是 single-threaded。您不能在执行过程中中断函数,因为它会阻止线程调用 onclick
回调,直到其执行完成。
但是,您可以使用 generator:
设计可中断函数
function resumeTimer() {
task.resume();
}
function stopTimer() {
task.pause();
}
// the `*` means this is a generator function
function* foo() {
let i = 0;
while (true) {
// every `yield` statement is a point
// where control-flow is interrupted
yield console.log(i++);
}
}
class Task {
constructor(iterator, ms = 16, autoplay = true) {
this.step = this.step.bind(this);
this.iterator = iterator;
this.ms = ms;
if (autoplay) {
this.resume();
}
}
step() {
this.result = this.iterator.next((this.result || {}).value);
}
pause() {
if (this.ref) {
clearInterval(this.ref);
this.ref = null;
}
}
resume(ms = this.ms) {
if (ms !== this.ms) {
this.pause();
this.ms = ms;
}
if (!this.ref) {
this.step();
this.ref = setInterval(this.step, this.ms);
}
}
}
let task = new Task(foo());
<button id="play-button" onclick="resumeTimer();">Play</button>
<button id="pause-button" onclick="stopTimer();">Pause</button>
参考资料
我有三个功能:
let timeVar;
let savedFunctionCode;
function startTimer(code) {
savedFunctionCode = code;
timeVar = setTimeout(savedFunctionCode, 2000);
}
function resumeTimer(intervalTime = 2000) {
setTimeout(savedFunctionCode, intervalTime);
}
function stopTimer() {
clearTimeout(timeVar);
}
这样做的唯一目的基本上是一种暂停和恢复特定代码的方法。
现在在定时器被实例化后(通过调用 startTimer)可以暂停或恢复代码。
如果方法 stopTimer() 和 resumeTimer() 的调用间隔至少两秒,则暂停和恢复代码执行的预期行为有效。
但是,如果按照该顺序调用 resumeTimer() 和 stopTimer() 的时间少于两秒,stopTimer() 将不会成功 stop/pause resumeTimer() 预期执行。
我的理论:
在暂停状态下,调用 resumeTimer 时,代码会在两秒内执行。但是,如果您快速执行 stopTimer() ,则基本上没有什么可以停止的,因为 resumeTimer 的代码执行尚未开始。 (不到两秒)。
因此在两秒内 resumeTimer() 方法执行其代码,因为 stopTimer() 不会影响它。
问题: JavaScript 有没有办法让我执行 stopTimer() 时它会取消所有挂起的代码执行。所以在这种情况下,我希望 stopTimer() 取消将在 2 秒内发生的 resumeTimer() 代码执行。
如有不明白请指出。
示例:
<html>
<body>
<div id="media-holder">
<span id="play-button" onclick="resumeTimer();"></span>
<span id="pause-button" onclick="stopTimer();"></span>
</div>
<script>
let timeVar = setTimeout(execute, 2000);
function resumeTimer(intervalTime = 2000) {
setTimeout(execute, intervalTime);
}
function stopTimer() {
clearTimeout(timeVar);
}
function foo() {
for(let i = 0; i < 100; i++) {
console.log("execute");
}
}
</script>
<html>
如果你快速点击播放按钮和暂停按钮,它仍然会继续执行foo()方法,
JavaScript 是 single-threaded。您不能在执行过程中中断函数,因为它会阻止线程调用 onclick
回调,直到其执行完成。
但是,您可以使用 generator:
设计可中断函数function resumeTimer() {
task.resume();
}
function stopTimer() {
task.pause();
}
// the `*` means this is a generator function
function* foo() {
let i = 0;
while (true) {
// every `yield` statement is a point
// where control-flow is interrupted
yield console.log(i++);
}
}
class Task {
constructor(iterator, ms = 16, autoplay = true) {
this.step = this.step.bind(this);
this.iterator = iterator;
this.ms = ms;
if (autoplay) {
this.resume();
}
}
step() {
this.result = this.iterator.next((this.result || {}).value);
}
pause() {
if (this.ref) {
clearInterval(this.ref);
this.ref = null;
}
}
resume(ms = this.ms) {
if (ms !== this.ms) {
this.pause();
this.ms = ms;
}
if (!this.ref) {
this.step();
this.ref = setInterval(this.step, this.ms);
}
}
}
let task = new Task(foo());
<button id="play-button" onclick="resumeTimer();">Play</button>
<button id="pause-button" onclick="stopTimer();">Pause</button>