9

I'm having trouble running an animation. This is inside var ob1 = function() {};. When called, it runs for a while and then I get the error Uncaught RangeError: Maximum call stack size exceeded. However, this same structure has no problems running outside of the object.

/////////////// Render the scene ///////////////
this.render = function (){

        renderer.render(scene,camera);
        if(isControls == true) controls.update(clock.getDelta());
        this.animate();
        //console.log(true);
        requestAnimationFrame(this.render());
}

/////////////// Update objects ///////////////
this.animate = function (){
        console.log("!");
}
JVE999
  • 3,327
  • 10
  • 54
  • 89

2 Answers2

24

You should pass a function reference to requestAnimationFrame, not invoke the function:

requestAnimationFrame(this.render);

Since you're using this inside render, you'll probably need bind:

requestAnimationFrame(this.render.bind(this));

Your version is causing a Stack Overflow (the function is calling itself synchronously, until the call stack is full).


bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • That's actually what I tried first, because that's what I normally do, but it doesn't work. It runs only 1 time and tells me this.animate() doesn't exist, after running this.animate(). If I put it as the first thing, I get `Uncaught TypeError: Type error cleanedupmenufunctions.php:167 render` – JVE999 Oct 18 '13 at 21:50
  • I just updated my answer, you need a bound function, with a fixed `this` value. – bfavaretto Oct 18 '13 at 21:51
  • Ah, the line `requestAnimationFrame(this.render.bind(this));` works great! No errors after several refreshes. – JVE999 Oct 18 '13 at 21:51
  • 1
    Note that bind is not supported on older browsers. The MDN link I provided includes a polyfill. – bfavaretto Oct 18 '13 at 21:52
  • 2
    You don't want to use bind this way as you're creating a new function object every time you call bind. Instead you want to bind beforehand at init time as in `const render = this.render.bind(this);` then in your loop call `requestAnimationFrame(render)`. You could also do it the react way, in your constructor do `this.render = this.render.bind(this);` then you can call `requestAnimationFrame(this.render);` – gman Jul 27 '17 at 09:33
0

Something I did to get this to run from a class that I saw from another example was to do this.

requestAnimationFrame(() => {
      this.animate()
})

This seems to get around the issue as well without any issues!

Here is a threeJS example of me using this from within a class

https://jsfiddle.net/gentleman_goat66/o5wn3bpf/107/

Joseph Astrahan
  • 8,659
  • 12
  • 83
  • 154