我对构建HTML5游戏时遇到的情况有疑问,导致难以管理循环依赖。
我完全理解为什么会发生循环依赖以及它在何处发生。但是,我似乎无法找到一种方便的方法来解决它,因此我认为我的逻辑/方法存在根本缺陷。
以下是一些背景信息。
我有一个游戏,它有一个名为Game.js
的单一入口点(使用Webpack编译)。我有一个基本的事件管理器,允许两个函数on(key, callback)
和fire(key, parameters)
。
事件管理器只是创建一个对象,将提供的on
键设置为一个属性,其数组值填充了注册到该键的任何callback
函数。调用fire
方法时,将检索该属性,并调用其数组值中定义的所有函数。
我正在尝试做什么
我希望能够在Game.js
上实例化事件管理器并导出其他类可以导入的Game
实例,然后将回调注册到Game
实例事件管理器。 / p>
class Game {
constructor() {
this.events = new EventManager();
window.addEventListener('resize', this.resize.bind(this));
}
resize(event) {
if(window.innerWidth < window.innerHeight) {
this.events.fire('orientation-change', 'vertical');
} else {
this.events.fire('orientation-change', 'horizontal');
}
}
}
export default new Game();
然后,例如Button
类可能需要响应Game
触发的方向更改事件。请注意,以上只是事件管理器可以发起事件的情况的示例,但这种情况可能是任何事情。
import Game from '../core/Game';
class Button {
constructor() {
Game.events.on('orientation-change', this.reorient.bind(this));
}
reorient() {
// ...
}
}
export default Button;
上面的类是一个名为Button的UI组件,需要知道orientation-change
事件何时被触发,请再次注意,此事件可能是任何。
有什么问题?
上面没有什么看起来特别错误,因为Game.js
是入口点,在某些时候创建Button的实例,无论是直接在Game.js
还是通过另一个类,通过Game.js
实例化,这当然会导致循环依赖,因为即使不是直接依赖,Game
导入Button
和Button
导入Game
。
我尝试了什么
我发现有两种主要的解决方案可以工作(在某种程度上)。第一个是在Button
的构造函数中使用间隔检查Game的值来等待导出可用,如下所示:
import Game from '../core/Game';
class Button {
constructor() {
let check = setInterval(() => {
if(Game !== undefined) {
Game.events.on('orientation-change', this.reorient.bind(this));
clearInterval(check);
}
}, 100);
}
reorient() {
// ...
}
}
export default Button;
这通常会在一次迭代中解决。
第二种解决方案是使用依赖注入并在实例化时传递Game to Button的引用,这也很有用,但是每个类不得不反复执行此操作的前景似乎不直观。间隔检查工作正常,但似乎很hacky。
我觉得我完全错过了一些东西,而且解决方案并不困难,因为我正在制作它。
感谢您提供任何帮助。