关于javascript:如何动态导入全局类构造函数?

How to dynamically import a global class constructor?

如此处(或此处)所示,我们可以在许多浏览器和NodeJ中使用外部类定义。但是,加载外部类的最有用方法是

1
2
3
4
import('./MyClass.js').then(({default: MyClass}) => {
   let x = new MyClass(); // using here!
   // ... but it is not global, is AN ISLAND IN A BLOCK
 }); // async loading

...但是它不是全局的,是异步块中的一个孤岛。 那么,如何在全球范围内做呢?

测试全球替代方案和错误:

1
2
3
4
5
6
 const MyClass = () => import('/MyClass.js'); // ok, but...
 let x = new MyClass()
 // Uncaught TypeError: MyClass is not a constructor

 const MyClass = await import('/MyClass.js');  
 // Uncaught SyntaxError: await is only valid in async function

建议使用module = await import(moduleFile)形式。

对于"全局类",假设这样的外部Javascript文件MyClass.js

1
2
3
4
5
6
export default class MyClass {
  constructor(x) {
    this.val=x? x:"Hello!"
    console.log("MyClass ok...")
  }
}


通常,在使用模块时,您不希望全局执行操作。这是模块要点的一部分。

如果要动态导入,那么根据您所执行的操作的性质,它将是一个异步过程,这意味着要等待它完成的代码(例如,then处理程序或在其中使用await async函数)。

您可以在then处理程序中(或在async函数中的await之后)写入全局变量,但这通常是个坏主意,因为在一段时间内,全局变量没有该值(然而)。

1
2
3
4
5
6
7
8
// **NOT** RECOMMENDED
import("/MyClass.js")
.then(cls => {
    window.MyClass = cls; // Or `global.MyClass = cls;` on Node.js
})
.catch(error => {
    // Handle error
});

或到全局模块:

1
2
3
4
5
6
7
8
9
// **NOT** RECOMMENDED
let MyClass;
import("/MyClass.js")
.then(ns => {
    MyClass = ns.default;
})
.catch(error => {
    // Handle error
});

(请注意,从动态import接收的是模块名称空间对象。在这种情况下,您使用的是默认导出,可通过MNO上的default属性对其进行访问。)

但是,在这两种情况下,代码都可能在填充之前尝试使用它。更多:如何从异步调用返回响应?

相反,基本上,将所有需要该类的代码放在then处理程序中,或放在await之后的async函数中。现场例子

1
2
3
4
5
6
7
8
9
(async () => {
    const {default: MyClass} = await import("./MyClass.js");
    let c = new MyClass();
    // ...
})()
.catch(error => {
    // Handle/report error
    console.error(error);
});

(请注意,要从MNO的默认值中获取MyClass进行解构。)

另请参阅:如何在顶层使用async / await?