Search code examples
javascripttypescriptsystem.jsimport-maps

How to import a service-like singleton-class with System.js?


I have a Singleton-Class FooService that is loaded via an import-map. I'd like to (a)wait for it and use it in various async functions like so:

declare global {
  interface Window {
    System: System.Module
  }
}

const module = window.System.import('@internal/foo-service')
const fooService = module.FooService

async function func1() {
  await fooService.doBar()
  .
  .
}

async function func2() {
  await fooService.doBar2()
  .
  .
}

But I could only get it to work like this:

declare global {
  interface Window {
    System: System.Module
  }
}

async function getfooService() {
  const module = await window.System.import('@internal/foo-service')
  return module.FooService
}

function func1() {
  getfooService().then(fooService => fooService .doBar())
  .
  .
}

function func2() {
  getfooService().then(fooService => fooService.doBar2())
  .
  .
}

How can I achieve this without loading it anew every time I want to use it?


Solution

  • Your first guess was nearly fine. Notice that the module returned by import is a promise, so you need to use it as

    const fooService = window.System.import('@internal/foo-service').then(module =>
      module.FooService
    );
    
    async function func1() {
      (await fooService).doBar();
    //^                ^
      …
    }
    
    async function func2() {
      (await fooService).doBar2();
    //^                ^
      …
    }
    

    Btw I would recommend to avoid using a FooService "module object" (or worse, class) and instead just export named functions, so that you can drop the .then(module => module.FooService).