1

I've been using @zzzzBov's fantastic loadScript() function to load JS libraries using Promises. However, it becomes tedious and messy to chain together Promises for all of the loaded libraries. I'd like to switch to an async/await solution, but—since loadScript() function doesn't return the usable library objects I need—this isn't as straightforward as using .then() at a first glance.

The function returns a load Event, which I await. So my initial approach would be to just define some useless constants as the Promise returns, and then reference them in an if statement:

let loadedGlobalObject: any;
const lib1Loaded: Event = await loadScript(lib1URL);
const lib2Loaded: Event = await loadScript(lib2URL);

if (lib1Loaded && lib2Loaded) { // Makes this block dependent upon the await statements
   loadedGlobalObject = (window as any).globalObject;
   console.log(loadedGlobalObject);
}

Is this correct form? I don't know how to "invoke" the await statements; an if statement was my first guess. So I'm wondering if this is the best solution, or if there is a more efficient/accepted technique (I know that I could substitute the libXLoaded constants into the if statement, but I'm going for readability).

Jordan Mann
  • 402
  • 6
  • 16

2 Answers2

0

If I understand what you are trying to do - you want to await the loading of your libraries, and access the global objects only once they are loaded. What about something like this:

try {
  async function loadLibs () {
    const lib1Event: Event = await loadScript(lib1Url);

    let loadedGlobalObject: any;
    loadedGlobalObject = (window as any).globalObject;
    console.log(loadedGlobalObject);
  }

  loadLibs();
  
catch (err) {
  console.log('Error loading script: ', err);
}

The loadScript() function rejects if there was an error while loading the script, so you can wrap your code in a try...catch. Otherwise, it resolves and you can access it's global object.

Note that you can only call await within a function marked as async.

dwosk
  • 1,202
  • 8
  • 11
0

So it turns out I didn't understand async/await at all. I had thought that the awaited constants were reactive, and lines referencing them were run only after their Promises resolved; instead, it's just the rest of the function that waits.

For error-handling, as @dwosk answered, you can use a try-catch, although I wasn't concerned about this. As @Rezaa91 commented, I could have used an await Promise.all([]), except for that I'm loading dependencies in order. And, now that I understand await statements better and as @dwosk and @Bergi noted, I don't need to define those constants.

In summary, my modified code (with Promise.all() added for fun) looks like this:

let loadedGlobalObject: any;
await Promise.all([loadScript(dependency1), loadScript(dependency2)]);
await loadScript(library1);
// Will have been loaded by now.
loadedGlobalObject = (window as any).globalObject;
console.log(loadedGlobalObject);
Jordan Mann
  • 402
  • 6
  • 16