How does observable/runtime consume generators?

Hi there,

I have to preface my question with an admission that I am a bloody noob, so please be kind. I might not be using the right jargon here, and so may be a little misled, but am keen to learn and will endeavor to describe as best as I can what is wrong.

I am having a little difficulty converting an Observable Notebook (Metaballs / Mike Bostock / Observable) into a VanillaJS project.

The issue: the generator seems to be yielding correctly, but the animation does not show and the page to grinds to a halt.

I think the problem resides in how the reactive runtime environment consumes the cell containing the generator. I have looked at the runtime codebase and have noticed a lot of Promise chaining, and therefore the opportunity for manual garbage collection… so feel like I am missing this in my rewrite… and this is the cause for the sluggishness (memory allocation?).

Has anybody else encountered this when attempting a rewrite from scratch?

I really appreciate any help that can be offered. I am really sorry if I have been poor at communicating my issue here. Just let me know what more I can provide.

Thanks for your help.

If you like, you can replace the cell with the loop with something like:

{
  gl.useProgram(program);
  gl.enableVertexAttribArray(a_corner);
  gl.vertexAttribPointer(a_corner, 2, gl.FLOAT, false, 0, 0);

  function step(now) {
    gl.uniform2f(
      u_ball1,
      (Math.sin(now / 3700) / 4 + 0.5) * width,
      (Math.cos(now / 3700) / 3 + 0.5) * height
    );
    gl.uniform2f(
      u_ball2,
      (-Math.sin(now / 900) / 3 + 0.5) * width,
      (Math.cos(now / 900) / 5 + 0.5) * height
    );
    gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

    window.requestAnimationFrame(step)
  }

  window.requestAnimationFrame(step);  
}

Does that help?

1 Like

Hi @jrus,

That worked perfectly! Thanks for your help. Though without seeing the code, would you have a recommendation as to why iterating over the generator would have caused the crash? I would get the anticipated logs… but the app would slow to a halt and the animation would not show. Any thoughts?

Thanks for all your help. I really appreciate your taking the time.

Without seeing the code you were trying it is hard to be sure exactly what was happening.

‘now’ is not a thing in bare javascript. So if you want to port it elsewhere, you need to make your own:

const now = function*() {
  while (true) {
    yield Date.now();
  }
}

https://github.com/observablehq/stdlib/blob/master/src/now.js

And then you need to start up some kind of run loop of your own to get your generator functions going.

window.requestAnimationFrame(step) is an alternative (non-generator-related) way to get code executing in a loop. Note that the callback given to requestAnimationFrame will already get passed the current timestamp, so when using requestAnimationFrame there is no explicit need to make your own timestamp generator.

@jrus, no problem. You are one-hundred-percent right in it being a stab in the dark without the code. Regardless, thanks for all your help. You definitely solved my issue. I suppose I just need to get more acquainted with promise chaining and generators if I am to understand what was the original issue in my code.

Thanks for everything.