bruns8234
bruns8234

Reputation: 51

JavaScript Scope and setTimeout inside of a "class"

I have trouble to solve a scope issue. Actually I'm working on a project for an HMI browser frontend. It's should visualise variables from an automation system. For the HMI it's required that the user can switch between different pages. To solve the general process flow I have created a state machine function, which coordinates loading, drawing and interaction with user. My problem now is that I use setTimeout to call the run function (which is actually my state machine) and now run in trouble with var-scope.

Look at following code:

function frontend() {

  // Public properties:
  this.soundEnable = true;

  // Private Properties:
  var p1 = 0;
  var p2 = [1,2,3];
  var p3 = {a:1, b:2, c:3};
  var runState = 1;
  var runWait = false:

  // Public Methods

  // stops the state machine until m_continue is called
  this.m_wait = function() {
    runWait = true;
  }

  // continues the state machine
  this.m_continue = function() {
    if (runWait) {
      runWait = false;
      setTimeout(run, 100);
    }
  }

  // Private Methods

  function drawFrame(finish_callback) {
    ...<Drawing of HMI-Objects on the canvas>...
    finish_callback();
  }

  function run() {
    switch (runState) {
    case 1:
      this.m_stop();
      drawFrame(this.m_continue());
    case 2:
      for(i=0; i<p3.length; i++) {
        p2.push(externalObjectCreator(p3[i]));
      }
    }
    if (!runWait) {
      runState++;
      setTimeout(run, 100);
    }
  }

  // Constructor
  ...<code to assign public and private properties>...

  // Finally call the state machine to activate the frontend
  runState = 1;
  run();
}

Problem is scope in run-Function. In case of the first call from end of constructor everything is ok. run can access all the private properties and manipulate them. But when it is called later on via setTimeout from m_continue or by itself I can't access the private properties. In firebug I can just see the public properties and functions and none of the private properties I need.

Using of global variables will help, but is not possible, because on multi monitor solution I have 2 separated canvas objects which need to show a separated version of the HMI - for that case I need 2 instances of frontend running parallel in one browser window.

Does anyone know a solution for that problem? I'm on the end of my knowledge and totally confused.

Upvotes: 0

Views: 902

Answers (2)

GameAlchemist
GameAlchemist

Reputation: 19294

You should bind the run function in each setTimeout, since run uses this.

setTimeout(run.bind(this), 100);

Upvotes: 0

user160820
user160820

Reputation: 15210

The easiest way will be to define your scope like. Any many renound javascript libraries also use this technique.

this.m_continue = function() {
 that = this;  
 if (runWait) {
      runWait = false;
      setTimeout(that.run, 100);
    }
  }

Otherwise you may also use scope binding using apply

Upvotes: 1

Related Questions