Async issues when wrapping a WebAssembly module into a Web Component

  custom-element, javascript, web-component

I have a WebAssembly module that renders some stuff on an HTML5 WebGL canvas. Everything works as it should. However, I would like to wrap everything up in a Web Component to simplify the usage of that module.

The WebAssembly module is quite large and hence takes a couple of seconds to download. There is a JavaScript callback function that is invoked once the download of the WebAssembly module is done.

The give some optical feedback to the user that something is going on while the module download is in prograss I’m drawing an animation to the canvas while the module is being downloaded. That animation is stopped in the callback function and the module is instantiated there.

Conceptually, I’m struggling to combine that JavaScript callback function with the class that represents the Web Component. Here’s what I have so far:

// Code that starts downloading the WebAssembly module (asynchronous)
...

var downloadAnimation;

// The class that represents the custom Web Component
class MyWebComponent extends HTMLCanvasElement {
  constructor() {
    super();
    // Initialization
    ...
  }

  connectedCallback() {
    // Start the animation indicating to the user that a download is in progress
    downloadAnimation = new DownloadAnimation(this);
    downloadAnimation.start();
  }

  // custom functions and properties enabling the usage of the WebAssembly module
  ...
}

// Register the custom Web Component so that instances of it can be created.
// If this were to be done in the onModuleReady callback function there would
// not be an animation that runs while the download is in progress.
if(!customElements.get("MyWebComponent")) {
  customElements.define("MyWebComponent", MyWebComponent, { extends: "canvas" });
}

// Called once the WebAssembly module is downloaded, i.e. when we're ready to instantiate it
function onModuleReady() {
  // First, the download animation is stopped
  downloadAnimation.stop();

  // Next, I could instantiate the WebAssembly module as shown below.
  // But how do I connect that instance with the instance of the Web Component
  // that is created via HTML?
  let myWebAssemblyInstance = new Module.MyCustomClass();
}

To be able to run the download animation the Web Component must be created before the WebAssembly module is downloaded. Therefore, I cannot simply execute customElements.define in the onModuleReady callback function. That would be too late to start the animation.

Once the module is downloaded I can start creating instances of the it. But I don’t see how I can connect such instances with the Web Component instance that gets created via HTML. Because I’m outside of the class that represents the Web Component, I don’t know how to access it.

Is there a way to access Web Component instances outside of the class that represents those instances, e.g. from within onModuleReady?

Or, more generally, is anyone seeing a better approach to handle this?

Source: Ask Javascript Questions

LEAVE A COMMENT