5

If I have a module "externals.js" that contains:

import * as three from "'https://cdn.jsdelivr.net/npm/three@0.110.0/build/three.module.js";
export three;

then I can use it without difficulty from "main.js" as so:

import three as J3 from "./externals.js";

var renderer = new J3.WebGLRenderer();
// ... do lots of cool stuff with the renderer

In particular, by the time execution gets to the call to WebGLRenderer, three.js is all loaded up and I successfully obtain a renderer.

However, if I would like to follow what appears to be a best practice as per Best way to use Google's hosted jQuery, but fall back to my hosted library on Google fail and fall back to a locally cached copy in case cdn.jsdelivr.net is unreachable, the only way I could find to do things in "externals.js" is to use async functions and dynamic import, like so:

export var three;
export var threeLoaded = new Promise(async function(resolve, reject) {
    var success = false;
    try {
        three = await import('https://cdn.jsdelivr.net/npm/three@0.110.0/build/three.module.js');
        console.log("original import OK");
        success = true;
    } catch(err) {
        try {
            three = await import('./node_modules/three/build/three.module.js');
            success = true;
            console.log("used fallback import");
        } catch(err) {
        }
    }
    if (success) { resolve(); } else { reject(); }
});

But now if I leave "main.js" as it is, and if there is any appreciable network delay in obtaining three.js, then J3.WebGLRenderer is undefined at the point that I try to use it and the main application fails. Instead, the only way I could find to proceed in "main.js" in this case is like so:

import { threeLoaded, three as J3 } from './externals.js';
main = function() {
    var renderer = new J3.WebGLRenderer();
    // ... do lots of cool stuff with the renderer
}
threeLoaded.then(main);

But at least for a simple "main.js," to me this code structure obfuscates the intention that I just want to import some modules and then execute some functions from them, sequentially.

So, the question: is there a way with the ES6 import facility to fall back to a local copy of a module but still have the import operation occur synchronously so that the module is available in the next line of code, as happens with an ordinary single "import" command?

Glen Whitney
  • 446
  • 2
  • 12
  • Since posting this, I found out about the "top-level await" ECMAscript proposal (https://github.com/tc39/proposal-top-level-await) which would solve this issue; I am still curious whether anyone knows of a way to do this without that mechanism. – Glen Whitney Dec 11 '19 at 16:26

0 Answers0