Codesmith
Codesmith

Reputation: 6752

using javascript setTimeout causes a loss of data within an object?

Background:
I've written a javascript object called Step to implement a step-type event for any operation I might need to use for my website, e.g. smooth-motion functions. I can register functions in it to run each step by using the Step object's method, registerFunction(func).

To handle running the functions every step, the Step object has another method called run(). In this method I run through the list of registered functions, run them, and then call the setTimeout(...) function, passing the reference to the run function to recall it for the next step.

Problem:
The first 'step' is run by the onload event (attribute) in the <body> tag of my html page (indirectly, though: Step.run is called by a function initiateJS() which is called by onload). Nothing goes wrong in the first step. However, by the second step, the variables within the Step object seem to have been disposed; they all become undefined.

Questions:
I was thinking it might be due to the garbage collector? Maybe it somehow loses its reference?
Also, is using setTimeout(...) even the best method of making a step-type event implementation?

Details:
The Step object is declared in the js document somewhat as:

    var Step = {
            myVars: "somevalues",
            anArray: [],
            run: function() {
                //run the registered functions
                setTimeout(this.run,this.interval);
        };

ALSO, in the next step, the Step object is still existent.

Some other minor details:

  • I'm using Chrome
  • I'm making my website with XAMPP full
  • I'm using Windows 7
  • Upvotes: 1

    Views: 404

    Answers (2)

    bhamlin
    bhamlin

    Reputation: 5187

    setTimeout runs code in the global context. this is no longer defined the next time run() executes. You'll need to refactor your code to either declare variables on some kind of global object, or to pass references into the run function itself.

    edit: since you said Step is global, this should work:

    run: function() {
        //run the registered functions
        setTimeout(Step.run, Step.interval);
    }
    

    Upvotes: 1

    Elias Zamaria
    Elias Zamaria

    Reputation: 101063

    Change your run function to this:

    run: function() {
        var that = this;
        setTimeout(that.run, that.interval);
    }
    

    The setTimeout function redefines the this variable and this is the simplest way I can think of to work around this issue.

    Upvotes: 1

    Related Questions