ScottK

Using a non-global function as requestAnimationFrame callback

Recommended Posts

I'd like to encapsulate my PIXI rendering in a JavaScript Prototype Object-Oriented fashion. The problem I'm running into is that there is no 'this' object when my animate method is invoked as the callback from requestAnimationFrame(). Can someone suggest a means to do this? I realize this is likely just a general JavaScript issue, as opposed to something related to PIXI, so sorry if this is trivial. Thank you in advance of any help you can provide!

Here is what I believe is the minimal code needed to demonstrate the issue:

var FFT = function() {
    this.renderer = PIXI.autoDetectRenderer(600, 800, {antialias: true});
    document.body.appendChild(this.renderer.view);
    this.stage = new PIXI.Container();
    this.stage.interactive = true;
    this.graphics = new PIXI.Graphics();
    this.stage.addChild(this.graphics);
};

FFT.prototype.renderLines = function() {
    // todo render lines here
};

FFT.prototype.renderLoop = function() {
    // when this method is invoked via the requestAnimationFrame
    // callback there is no 'this' object bound, so this.graphics
    // is undefined. my goal is to avoid adding global functions,
    // if possible.
    this.graphics.clear();
    this.renderLines();
    this.renderer.render(this.stage);
    requestAnimationFrame(this.renderLoop);
};

FFT.prototype.start = function() {
    this.renderLoop();
};

var fft = new FFT();
fft.start();

 

Share this post


Link to post
Share on other sites
//1. use bind
requestAnimationFrame(this.renderLoop.bind(this));
//2. use new function
var self = this;
requestAnimationFrame(function() { self.renderLoop(); } );
//3. use ES6
requestAnimationFrame(() => { this.renderLoop() } );

//4. bind function in constructor
function FFT() {
//...
    this.renderLoop = this.renderLoop.bind(this);
}

One cannot just walk into mordor^W^W^W use "this" in the function that is passed somewhere.

Crash course on javascript.

Share this post


Link to post
Share on other sites
5. Use class properties 
// This is still in draft but compilers such as babel or webpack can be configured to understand it

class Foo {
  constructor() { ... }

  loop = () => {
    raf( this.loop )
  }
}

Note that natively this is currently supported nowhere, babel transpilation turns it into number 4 in Ivans examples. 

Use bind, get in to good habits.

Using the arrow function is fine but it does not bind scope to the function, instead it invalidates this, which means that scope is inferred from the outer scope of the function. "Wat?", yeah, its confusing. The upshoot is, arrow functions usually work as you probably expect, but not absolutely everywhere. This is a great article on the subject.

Note that by binding functions you are creating a new instance of the function for every object you create, whereas normally JS will try to be smart about function invocation and grab them from the prototype. In your case it will not matter at all but it is something to consider if you are creating 1000+ objects with bound functions.

And for your own piece of mind, this is not trivial. JS scoping rules can get a little funky so get your head round them early. I've tried to hire too many contractors who are shaky on these details and I just can not trust them, and they're asking for a lot per day. Get learning this stuff early, your future self will thank you.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.