Ian Boyd Ian Boyd - 2 months ago 45
TypeScript Question

How to use requestAnimationFrame with a TypeScript object?

I have an object that i want to do drawing on a canvas. It will use

requestAnimationFrame
to start a game loop:

Contoso.ts

class Contoso
{
//private ctx: CanvasRenderingContext2D;

Initialize(ctx: CanvasRenderingContext2D) {
//this.ctx = ctx;
Render();
}

Render() {
//...snip doing any actual drawing for the purpose of this question
requestAnimationFrame(this.Render);
}
}


app.ts

var contoso: Contoso;

contoso = new Contoso();
contoso.Initialize(canvas);


The first time someone calls
Initialize
, the
requestAnimationFrame
manages to correctly call
Render
.

The second time
requestAnimationFrame
calls
Render
, the
this.Render
is
undefined
and it crashes.

It's almost as though the object was destroyed after the initial call to
Initialize
.

What is going on?

Answer

You've lost this context. Two possible fixes:

class Contoso
{
   /* ... */

   // Use () => syntax so Render always gets 'this' context
   // from the class instance
   Render = () => {
      //...snip doing any actual drawing for the purpose of this question
      requestAnimationFrame(this.Render);
   }
}

The alternate fix is probably slightly clearer, but has the downside of making a lot more allocations (you probably don't want to allocate 1 closure per frame!)

   Render() {
      //...snip doing any actual drawing for the purpose of this question
      requestAnimationFrame(() => this.Render);
   }