Rolf B: top-level await bei dynamischem Import von Modulen

Hallo,

ich möchte aus einem ECMAScript-Modul heraus ein anderes importieren. Welches, stellt sich erst zur Laufzeit heraus. Dafür gibt's die Pseudofunktion import(), die ein Promise für ein Modul-Objekt liefern soll.

MDN sagt, dass sowas hier gehen soll:

let modul;
if (bedingung)
   modul = await import('impl1.js');
else
   modul = await import('impl2.js');

modul.aktion();

Das funktioniert. Solange impl.js nicht seinerseits einen import macht*. Sobald das passiert, hängt das import-Promise fest. Das impl-Modul wird zwar geladen, aber nicht ausgeführt.

Wenn ich await import aufteile, das Promise in einer Variablen speichere und darauf mit .then warte:

modulPromise.then(modul => modul.aktion());

funktioniert es wieder. Das Modul wird geladen und ausgeführt, und das modulPromise geht auf resolved.

Ich würde gerne wissen, warum await import() sich festfrisst, wenn das importierte Modul selbst noch imports enthält. Das ist kein Chrome-Bug. Firefox macht das Gleiche, das muss also etwas spezielles sein. Aber ich finde dazu auch keine passenden Treffer auf einschlägigen "Hilf mir" Seiten wie stackoverflow. Okay, jetzt gibt's einen, ich habe eine Frage dazu formuliert.

Rolf

--
sumpsi - posui - obstruxi
  1. Ich hab was gelernt bei StackOverflow.

    Mein Testbeispiel war nicht so reduziert, wie ich es hier dargestellt habe.

    Ich habe:

    main.js:

    export { hilfsobjekt };
    
    const hilfsobjekt = { ... };
    
    let modul = await import("./modul1.js");
    modul.testcall();
    

    modul1.js:

    import { XyClass } from "./XyClass.js";
    
    export function testcall() { ... };
    

    XyClass.js:

    import { hilfsobjekt } from "./main.js";
    
    export class XyClass { ... };
    

    Tjaaa, und dieser import des Hilfsobjekts, das eigentlich nur dazu da ist, ein paar Testhelfer bereitzustellen, schießt den await ab. Nehme ich den raus und injiziere das Hilfsobjekt über Parameter, funktioniert es.

    Aber: Wenn ich diesen zirkulären Import drin lasse, und main.js so abändere:

    (() => {
       let modul = await import("./modul1.js");
       modul.testcall();
    )();
    

    dann funktioniert's auch.

    Warum? Weiß der Geier.

    Rolf

    Rolf

    --
    sumpsi - posui - obstruxi