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?
Make your component listen (at root level) for an Event.
onModuleReady
then dispatches the Event, which bubbles up.
You probably want a CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
And beware you need composed: true
for Events to 'escape' shadowRoots
Conceptually no different than the standard onload
or DomContentLoaded
events
Notes:
you are not restricted to DataTypes in the CustomEvent details
payload.
You can add Function References
So a Receiver can execute Methods in/from the Element that dispatched the Event
Events are processed synchronous
For indepth Event handling see: What the heck is the Event Loop
https://www.youtube.com/watch?v=8aGhZQkoFbQ
Also see: https://pm.dartus.fr/blog/a-complete-guide-on-shadow-dom-and-event-propagation/