JavaScript 模块的加载顺序问题

问题描述 投票:0回答:1

Github 存储库:https://github.com/leighhobson89/ChipshopChopper

我很难强制一个

.js
文件在另一个文件尝试运行其代码之前运行其代码。问题的关键在于,我通过一个文件中的调度事件调用一个函数(我们称其为
1.js
),而它调用的函数位于第二个文件中(我们称其为
2.js
)。然而,即使它在事件分派触发时调用该函数,它应该在该函数中写入的变量返回未定义(它在
2.js
中的函数上方声明)

我尝试在分派事件之前在

1.js
中声明此变量并导出它,但随后出现错误,提示您无法分配给常量变量。这个练习的重点是在自己的文件中包含这个常量,因为它是一个很长的 DOM 元素列表,并且我不想每次想要影响某个元素的
document.getElementById()
时都必须继续调用
innerHTML 
元素,所以我创建了一个事件来触发在我希望它加载的代码中的某个点调用此函数,即在创建元素之后但在请求更改它们之前。

我想要一种方法,除了

defer 
或对HTML中的顺序进行排序,或者将脚本放在
<head>
标签中,所有这些我都尝试过但没有成功,强制它初始化
中的变量2.js
1.js
中执行任何操作之前。

如果有人想查看代码示例,我将提供它们,但是如果不从多个文件粘贴大量代码,就很难获得上下文,因此提前表示歉意。

根据在线研究,我尝试过:

  • defer 
    尝试在
    1.js
    之前加载
    2.js
  • 1.js
    放入
    <head>
    标签中
  • 在设置 elements 变量的函数中创建一个
    Promise 
    ,以解析何时 elements 的值不是 null 或未定义(但我没有很好的异步编程能力,所以它可能是对的,也可能不是)
  • 交换 HTML 文件中
    <script>
    标签的顺序。

1.js:

let elements;

export function setElements() {
      elements = {
        option1: document.getElementById('option1'),
        option2: document.getElementById('option2'),
        //etc
      }

2.js

import {getElements, setElements} from './1.js'

document.addEventListener('titleScreenCreated', setElements);
const titleScreenCreatedEvent = new Event('titleScreenCreated');
createGameWindow(titleScreenCreatedEvent);
//code that creates various elements
document.dispatchEvent(titleScreenCreatedEvent);
console.log(getElements());
//code that changes elements
// getElements().option1.innerHTML = "hello world";

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>Your Game</title>
</head>
<body>
<div class="clock">00:00:00</div>
<script type="module" src="actions.js"></script>
<script defer type="module" src="1.js"></script>
<script type="module" src="ui.js"></script>
<script type="module" src="2.js"></script>
</body>
</html>
javascript asynchronous es6-modules delayed-execution
1个回答
0
投票

感谢您链接 GitHub 存储库,这样我就能够重现您的问题。

当模块尚未完全加载时,您的游戏会尝试创建 UI。我建议创建一个

main
函数作为应用程序的入口点,并将游戏初始化的每一点都移到该函数中。确保在所有模块初始化后调用它,例如使用 DOMContentLoaded 事件

function main() {
  document.addEventListener('titleScreenCreated', settlements);
  const titleScreenCreatedEvent = new Event('titleScreenCreated');
  createGameWindow(titleScreenCreatedEvent);
  createTitleScreen();

  gameLoop();
}

document.addEventListener('DOMContentLoaded', () => {
  main();
});

更一般地说,只有当存在依赖循环时,您才会看到此类问题。当这种情况发生时,没有可靠的方法来控制加载顺序,你必须重构应用程序。解决这个问题的最佳方法是如果可能的话完全避免循环。

© www.soinside.com 2019 - 2024. All rights reserved.