5

我在 Javascript + BackboneJS(一个 MVC 框架)+ RequireJS 框架中工作,但这个问题有点面向对象。

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

一段时间以来一直在为此绞尽脑汁,但我不确定正确/务实的方法应该是什么。

我有一个 User 对象,其中包含许多代码所依赖的用户首选项(如单位系统、语言选择等)。

我的一些视图在不使用模板的情况下完成了大部分工作(通过使用 3rd 方库,如映射和图形库),因此它们依赖于 User 对象来处理单位转换。我目前正在使用 RequireJS 来管理该依赖项,而不会过多地破坏封装。

我的一些视图自己做的工作很少,只将模型数据传递给我的模板引擎/模板,这些模板引擎/模板完成工作并且确实依赖于用户对象,同样,用于单位转换之类的事情。将此依赖项传递到模板中的唯一方法是将其注入模型中,然后将模型传递到模板引擎中。

我的问题是,如何最好地处理如此广泛需要的依赖项?- 创建一个可在任何地方访问的应用程序范围的引用/全局对象?(YUK) - 使用 RequireJS 托管依赖项,尽管通常只建议对类/对象定义而不是具体对象使用托管依赖项加载。- 或者,只使用依赖注入,并手动将该依赖传递给需要它的所有东西?

4

3 回答 3

4

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

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

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

话虽如此,我更不支持拥有一些用户对象,我们一直在从一个功能到另一个功能,无限地传递。

就个人而言,不得不在这两个邪恶之间做出选择,我会选择一个全球范围的“很少改变”的事情——除非我正在建造一个核电站或其他什么东西。所以,我倾向于让登录用户在我的应用程序中全局可用,冒着风险,如果出于某种原因,某些呼叫运行得很晚,并且我遇到一个用户注销而另一个用户直接登录的情况,某事可能会发生奇怪的事情。(再说一次,如果流星坠入托管我的应用程序的数据中心,也可能会发生一些奇怪的事情......我也没有防止这种情况发生)。实际上,一个可能的解决方案是在有人注销后立即重新加载整个应用程序。

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

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

代替

doSomethingCoolWith(window.loggedinuser);

虽然最后都差不多...

于 2012-10-02T18:54:46.647 回答
1

我认为您已经回答了自己的问题,您只是希望其他人为您说:) 使用 DI,但您并没有真正“手动”将该依赖项传递给所有内容,因为无论如何您都需要引用它来使用它。

于 2012-10-02T18:21:53.430 回答
1

考虑到 TDD 方法,您将如何测试它?DI 最适合新项目,但 JS 为您提供了灵活的选项来在测试时处理具体的全局依赖关系,即:上下文构造。回顾过去,Yahoo 制定了一种模块模式,其中所有模块松散耦合并且不相互依赖,但可以拥有全局上下文。该全局上下文可以使您的应用程序构建对于不断重用的事物更加实用。只是您需要明智地/谨慎地应用它,并且需要非常有力的案例来证明这些事物是动态的。

于 2012-10-02T19:00:49.510 回答