依赖注入与托管依赖关系与全局对象的关系

时间:2012-10-02 18:10:14

标签: javascript oop model-view-controller backbone.js requirejs

我正在使用Javascript + BackboneJS(一个MVC框架)+ RequireJS框架,但这个问题有些OO泛型。

首先让我解释一下,在Backbone中,您的视图是传统视图和控制器的混合,您的HTML模板是传统的MVC视图

对此我一直在讨论这个问题,我不确定应该采用什么样的正确/务实方法。

我有一个User对象,其中包含许多代码所依赖的用户首选项(如单元系统,语言选择和其他任何内容)。

我的一些视图在不使用模板的情况下完成大部分工作(通过使用第三方库,例如Mapping和Graphing libs),因此它们依赖于User对象来处理单位转换,例。我目前正在使用RequireJS来管理这种依赖,而不会过多地破坏封装。

我的一些视图本身做的很少,只将模型数据传递给我的模板引擎/模板,这些工作和DO依赖于User对象,对于单位转换等事情也是如此。将此依赖项传递到模板的唯一方法是将其注入模型,并将模型传递到模板引擎中。

我的问题是,如何最好地处理这种广泛需要的依赖? - 创建一个可在任何地方访问的应用范围的参考/全局对象? (议员) - 使用RequireJS托管依赖项,即使通常只建议使用托管依赖项加载类/对象定义而不是具体对象。 - 或者,只使用依赖注入,并手动将该依赖项传递到需要它的所有内容中?

3 个答案:

答案 0 :(得分:4)

从纯粹的技术角度来看,我认为可交换的全局变量(可能会改变的全局变量),特别是在javascript中,是危险的和错误的。特别是因为javascript充满了异步执行的代码部分。请考虑以下代码:

window.loggedinuser = Users.get("Paul");
addSomeStuffToLoggedinUser();
window.loggedinuser = Users.get("Sam");
doSomeOtherStuffToLoggedinUser();

现在,如果addSomeStuffToLoggedinUser()在某处异步执行(例如,它执行ajax调用,然后在第一个调用完成时再调用另一个ajax),则很可能会向新的loggedinuser(“Sam”)添加内容,当它到达第二个ajax调用时。显然不是你想要的。

话虽如此,我甚至不再支持我们从一开始就无处不在地使用一些用户对象,无限制地。

就个人而言,不得不在这两种罪恶之间做出选择,我会选择一个“很少改变”的全球范围 - 除非我正在建立核动力或其他东西。因此,我倾向于在我的应用程序中使登录用户全局可用,冒了一些风险,如果由于某种原因某些调用运行很晚,我有一个用户退出并直接另一个登录的情况,某事奇怪的可能发生。 (再说一次,如果流星撞到托管我的应用程序的数据中心,也可能会发生一些奇怪的事情......我也不会反对这种情况)。实际上,一个可能的解决方案是在有人退出时立即重新加载整个应用程序。

所以,我猜这一切都取决于你的应用程序。让它变得更好的一件事(让你觉得你仍然得到一些OO业力点)就是将你的数据隐藏在一些命名空间的单例中:

var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
doSomethingCoolWith(myuser);

代替

doSomethingCoolWith(window.loggedinuser);

虽然最后几乎是一样的......

答案 1 :(得分:1)

我认为你已经回答了自己的问题,你只是想让别人为你说出来:)使用DI,但你并不是真的“手动”将依赖传递给所有东西,因为你需要引用它来使用它反正。

答案 2 :(得分:1)

考虑到TDD方法,您将如何测试? DI最适合新项目,但JS为您提供了灵活的选项,可以在测试时处理具体的全局依赖关系,即:上下文构造。回过头来看,雅虎制定了一个模块模式,其中所有模块都是松散耦合的,并且不依赖于彼此,但是可以拥有全局上下文。这种全局背景可以使您的应用程序构建更加务实,不断重用的东西。只是你需要谨慎/谨慎地应用它,并且需要有非常强大的案例才能使这些事物变得充满活力。