【问题标题】:A list of the namespaces created by import statements由 import 语句创建的命名空间列表
【发布时间】:2023-03-11 12:28:01
【问题描述】:

我有一个脚本标签 (type="module"),它由 PHP 根据一些参数动态填充 import 语句。填充过程由站点的授权系统控制,它可以从脚本中删除一些imports,这取决于当前用户的权限。

页面上最终呈现的脚本标签示例:

<script type="module">
    import ui from 'path_to_ui_module';
    import read from 'path_to_read_module';
    import edit from 'path_to_edit_module';     // Could be omitted by the authorization
    import create from 'path_to_create_module'; // Could be omitted by the authorization
    import delete from 'path_to_delete_module'; // Could be omitted by the authorization
    ui.init();
</script>

保证所有的导入都只是对象。

现在,问题出在ui.init 方法中,我想将已加载模块(及其子模块)的某些属性的一些引用分配给ui 中的属性,但我不知道,哪些模块实际加载,因为授权系统可能已经从脚本中删除了一些模块。例如,所有加载的模块都有一个包含各种方法的cmd 对象,我想将这些方法的引用分配给ui.cmd 对象。如何遍历导入模块的所有命名空间,包括脚本中加载的模块可能导入的子模块?

目前我已经修改了授权系统,创建了ui.init调用,它将真正加载的模块的引用传递给ui.init方法,但是子模块自然不包括在内。

ui.init({modules: {read: read, edit: edit, create: create, delete: delete});

(授权系统丢弃的模块不包含在modules对象中。)

使用传递的modules 对象,简化的ui.init 方法如下所示(cmets 中的“主模块”是ui,“子模块”是指通过参数传递的模块):

init (options) {
    for (const module in options.modules) {
        this[module] = options.modules[module];    // Add submodule reference to the main object
        this[module].main = this;                  // Add main module reference to submodule
        Object.assign(this.cmd, this[module].cmd); // Assign the cmd methods of the submodule to the main module's cmd object
        this[module].init();                       // Initialize the submodule
    }
}

修改后的问题:是否有所有导入模块的本机“列表”,包括导入模块已导入的子模块,可用,我可以在for .. in 循环中使用它来代替options.modules?或者,有没有办法让子模块在加载后以某种方式“暴露”自己,以便它们可以创建加载模块的列表?

【问题讨论】:

  • 现在,我最终在所有导入模块的本地代码中维护了一个已加载子模块的列表对象。导入模块的init 方法检查列表是否存在,并将列表作为属性分配给导入的对象。主模块的init 方法检查子模块的列表,并以列表作为参数递归调用自身。这个解决方案的一个缺陷是,主模块本身不能包含列表。因此,我仍然对提供所有已加载模块列表的答案感兴趣,最好不要向子模块添加任何代码。

标签: javascript es6-modules


【解决方案1】:

您可以尝试使用动态导入:
(我假设您的 PHP 脚本可以动态生成 .then 回调)

<html>
  <body>
    <script type="module">
      Promise
        .all
          ( [ import('./node_modules/the-answer/dist/the-answer.es.js')
            , import('./node_modules/the-answer/dist/the-answer.es.js')
            , import('./node_modules/the-answer/dist/the-answer.es.js')
            ]
          )
        .then(([{default: answer1}, {default: answer2}, {default: answer3}]) => {
          // You now know all the modules that have loaded ?
          console.log(answer1, answer2, answer3);
        });
    </script>
  </body>
</html>

因为import 的动态形式返回一个promise,所以你可以等待它们全部解析并可以访问它们。

the-answer 模块是 literally 这个:

export default 42;

这就是为什么我需要在 .then() 方法中解构每个模块,例如

.then(([{default: answer1}]) => alert(answer1))

【讨论】:

  • 是的,我可以修改 PHP 脚本来生成动态导入。但不知何故,我看不到已知模块导入的所有子模块如何与您的解决方案一起引用。我会尝试在我的代码中实现这一点,但我需要几个小时才能提供任何进一步的反馈(这里已经很晚了)。
  • 此代码可以替换静态导入,但它只能提供与我在问题中的代码相同的功能,即它无法检测导入模块加载的子模块。不幸的是,我无法使用答案,但这对未来的读者可能非常有用。
猜你喜欢
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多