最佳方式处理取消 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>

参考资料