Search code examples
javascripttypescriptclassdynamic-import

Using async js imports in exported classes


Given a package that exposes async/dynamic exports. Which I currently import this way (but I could import it differently):

(async function() {
  const libEd = await import("../../.cache/ed25519wars/index.js");
})();

I intend to re-expose some functions from libEd as part of a class:

export class Something {
  static from_X() {
    return libEd.genFromX();
  }

  do_Y() {
    return libEd.doY();
  }
}

How can I do this ?


For more info:

  • The package that exposes async/dynamic exports is generated by webpack packing webassembly. I'm not sure if I can change anything about this part
  • I could definitely change the way I import that package
  • I could also change the way I re-expose / group the functions (and use something else than a class)

Solution

  • There's a couple of ways I would approach this:

    1. If the class doesn't need to be instantiated immediately, then I would await the library loading, then pass it to the class constructor. This is the cleanest way as the library is always defined within the class.

    2. If the class must be instantiated before fetching the library, then methods in the class must handle the situation when it is not defined (e.g. not loaded yet). You can then call something like await myClassInstance.init() to fetch the library. I typically provide a fallback for each method if the library is not loaded yet, perhaps it returns an empty string or a dummy UI.

    EDIT: adding TypeScript example for option 1

    interface MyLibrary {
      libraryMethod: () => void;
    }
    
    class ExampleClass {
      localLib: MyLibrary;
    
      constructor(lib: MyLibrary) {
        this.localLib = lib;
      }
    
      myClassMethod() {
        this.localLib.libraryMethod();
      }
    }
    
    async function run() {
      // first we fetch the remote library
      const myLibrary: MyLibrary | undefined = await import('/lib.js');
    
      // good practise to add some check here
      if (!myLibrary) {
        throw Error('failed to fetch myLib');
      }
    
      // then we create the class instance using the downloaded library
      const myClassInstance = new ExampleClass(myLibrary);
    
      // now we can call our class method which definitely has the remote library
      myClassInstance.myClassMethod();
    }