0

I recently started learning javascript to help maintain some stuff and ran into this issue today:

this.moveChar = function(){  
    // body here
    setTimeout(moveChar,1000);
}

this.initialise= function(){
    this.moveChar();
}

When initialise is called, I expected moveChar to be called, then repeated call itself once every 1000ms

However, what actually happens is moveChar gets called once then that's it. Based on other stackoverflow posts I read, I suspected it might be something to do with the function being expressed rather than declared. I have tried to use

this.moveChar = function recMove(){  
    // body here
    setTimeout(recMove,1000);
}

without luck either.

Any suggestions on how I can fix this?

EDIT: Main thing I need to do is have the moveChar function called once every second. If there is a better approach than setTimeout recursion, I'm open to it

6
  • Are you using this in side body here? If so, you should bind correct context while call. Commented Jul 19, 2016 at 7:15
  • 2
    First if you wish to run a function after every specific delay, use setInterval. Second, when you do setTimeout(moveChar,1000);, JS will look for a variable with name moveChar and will not find anything. moveChar is a part of an object and has to be accessed as object.moveChar in your case this.moveChar. Now since you are looping recursively, you will have to bind this again. so your code becomes setTimeout(this.moveChar.bind(this), 1000) Commented Jul 19, 2016 at 7:16
  • yes the function moveChar uses some global variables by referring to them using this.VARIABLENAME if that's what you mean? Can you elaborate on the binding to context part? Commented Jul 19, 2016 at 7:19
  • @Rajesh, setInterval is completely other feature. with tail setTimeout you'll never get two calls at same time. Commented Jul 19, 2016 at 7:21
  • @Rajesh Thank you very much that fixed it completely. I tried setInterval earlier but it did not work, possible due to me not binding it properly Commented Jul 19, 2016 at 7:23

4 Answers 4

3

this.moveChar is not the same as moveChar, unless this is the global scope object like window.

this.moveChar is a property on an object, while moveChar would reference any variable in a visible scope chain.

You can change it to a couple of things in order to keep scope of whatever object is being used:

Using an arrow function

this.moveChar = function(){  
    // body here
    setTimeout(()=>this.moveChar(),1000);
}

Using .bind()

this.moveChar = function(){  
    // body here
    setTimeout(this.moveChar.bind(this),1000);
}
Sign up to request clarification or add additional context in comments.

Comments

1

You might want to consider using setInterval() which is the more appropriate API for this task.

What setInterval() does is - it will repeatedly call the given function upon a certain interval is reached.

See: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval

Quote:

Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. Returns an intervalID.

Example:

Assuming moveChar() contains your operation logic. Then to repeat it you'll do this 1 line.

let moveChar = function(){  
    // Do stuff
    console.log("Hi thanks for calling me!");
}

setInterval(moveChar, 1000);

2 Comments

I tried this and it did not execute a single iteration of the moveChar function for some reason
@kcns15 works on my machine at work. Did u just copy paste the code above and test it or u did some minor mods to it. If u do care to show your current code? Happy to assist further.
1

Are you using this in side body here?
If so, you should bind correct context while call.

this.moveChar = function(){  
    // body here
    setTimeout(this.moveChar.bind(this), 1000);
}

Or use anonymous function:

this.moveChar = function(){  
    // body here
    var that = this;
    setTimeout(function(){
      that.moveChar();
    }, 1000);
}

Or arrow function:

this.moveChar = function(){  
    // body here
    setTimeout(() => this.moveChar(), 1000);
}

Same notes apply to setInterval variant:

this.initialise= function(){
   setInterval(this.moveChar.bind(this), 1000);
   // var that = this;
   // setInterval(function(){that.moveChar();}, 1000);

   // setInterval(() => this.moveChar(), 1000);
}

6 Comments

He needs to repeat the execution, setInterval is needed here.
This setTimeout repeats the exeution. Why setInterval need here?
Check the second tip on this W3Schools Documentation
See A clock created with timing events on the same page
there is difference: setInterval don't wait previous calls, so it can spam calls.
|
-2
   this.moveChar = function(){  
       // body here
     alert('called moveChar');
  }

this.initialise= function(){
     setInterval(function(){moveChar();},1000);
}

 this.initialise();//call here

1 Comment

First, just putting code is not a good answer. You should explain what you have changed. Second, run your code before and then put it here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.