Source: src/main/js/common/TaskLooper.js

/**
 * Run a task in a fixed period loop.
 */
class TaskLooper {
  
  /**
   * Build the looper with a function to invoke on a fixed period loop.
   * 
   * @param {function} fn - the function to invoke
   */
  constructor(fn) {
    this.fn = fn;
  }
  
  /**
   * Start the task loop.
   * 
   * @param {int} periodInMs the loop period in milliseconds
   */
  start(periodInMs) {
    this.periodInMs = periodInMs;
    if (this.isStarted) return;
    this.isStarted = true;
    
    // start looping
    this._runLoop();
  }
  
  /**
   * Stop the task loop.
   */
  stop() {
    this.isStarted = false;
  }
  
  /**
   * Set the loop period in milliseconds.
   * 
   * @param {int} periodInMs the loop period in milliseconds
   */
  setPeriodInMs(periodInMs) {
    this.periodInMs = periodInMs;
  }
  
  async _runLoop() {
    if (this.isLooping) return;
    this.isLooping = true;
    let that = this;
    while (this.isStarted) {
      let startTime = Date.now();
      await this.fn();
      if (this.isStarted) await new Promise(function(resolve) { setTimeout(resolve, that.periodInMs - (Date.now() - startTime)); });
    }
    this.isLooping = false;
  }
}

module.exports = TaskLooper;