Optimal State Change Queue

by sperske

HTML

<button id='Action'>Star</button>
<ol id='LogOutput'></ol>

JavaScript

class StarManager {
	constructor(button, logOutput) {
  	this.button = button;
    this.logOutput = logOutput;
    this.isStarred = false;
		this.waitingFor = null;
		this.queue = [];
  }

  log(message) {
    var c = document.createElement('li');
    c.innerHTML = message;
    this.logOutput.append(c);  
  }

	toggleStar() {
  	this.isStarred ? this.unstar() : this.star();
  }

	star() {
    this.button.innerHTML = 'Unstar';
    this.isStarred = true;
    preformSlow('star', function() {
      this.log('star done saving');
    });
  }

  unstar() {
    this.button.innerHTML = 'Star';
    this.isStarred = false;
    preformSlow('unstar', function() {
      this.log('unstar done saving');
    });
  }

  preformSlow(direction, action) {
    if (waitingFor === null) {
      log('executing ' + direction);
      waitingFor = {
        direction: direction,
        action: action
      };
      setTimeout(function () {
        var waitedFor = waitingFor;
        waitingFor = null;
        if (queue.length === 0) {
          waitedFor.action();
        } else {
          var last = queue.pop();
          queue = [];
          if (last.direction == waitedFor.direction) {
            waitedFor.action();
            log('Ended where we started');
          } else {
            log('Ended on a different state');
            preformSlow(last.direction, last.action);
          }
        }
      }, 3000);
    } else {
      log('queueing ' + direction);
      queue.push({
        direction: direction,
        action: action
      });
    }
  }
}

var button = document.getElementById('Action');
var logOutput = document.getElementById('LogOutput');
var manager = new StarManager(button, logOutput);
button.addEventListener('click', manager.toggleStar);