Javascript RequireJS 依赖注入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7708194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:16:30  来源:igfitidea点击:

Dependency Injection with RequireJS

javascriptrequirejs

提问by Aaronius

How much can I stretch RequireJS to provide dependency injection for my app? As an example, let's say I have a model that I want to be a singleton. Not a singleton in a self-enforcing getInstance()-type singleton, but a context-enforced singleton (one instance per "context"). I'd like to do something like...

我可以在多大程度上拉伸 RequireJS 来为我的应用程序提供依赖注入?例如,假设我有一个想要成为单身人士的模型。不是自执行 getInstance() 类型单例中的单例,而是上下文强制单例(每个“上下文”一个实例)。我想做类似...

require(['mymodel'], function(mymodel) {
   ...
}

And have mymodel be an instance of the MyModel class. If I were to do this in multiple modules, I would want mymodel to be the same, shared instance.

并让 mymodel 成为 MyModel 类的一个实例。如果我要在多个模块中执行此操作,我希望 mymodel 是相同的共享实例。

I have successfully made this work by making the mymodel module like this:

我通过使 mymodel 模块像这样成功地完成了这项工作:

define(function() {
    var MyModel = function() {
        this.value = 10;
    }
    return new MyModel();
});

Is this type of usage expected and common or am I abusing RequireJS? Is there a more appropriate way I can perform dependency injection with RequireJS? Thanks for your help. Still trying to grasp this.

这种类型的用法是预期的还是常见的,还是我在滥用 RequireJS?有没有更合适的方法可以使用 RequireJS 执行依赖注入?谢谢你的帮助。仍在努力掌握这一点。

回答by Domenic

This is not actually dependency injection, but instead service location: your other modules request a "class" by a string "key," and get back an instance of it that the "service locator" (in this case RequireJS) has been wired to provide for them.

这实际上不是依赖注入,而是服务位置:您的其他模块通过字符串“key”请求“类”,并返回“服务定位器”(在本例中为 RequireJS)已连接到的它的实例为他们提供。

Dependency injection would involve returning the MyModelconstructor, i.e. return MyModel, then in a central composition rootinjecting an instance of MyModelinto other instances. I've put together a sample of how this works here: https://gist.github.com/1274607(also quoted below)

依赖注入将涉及返回MyModel构造函数,即return MyModel,然后在中央组合根中将的实例MyModel注入其他实例。我在这里整理了一个如何工作的示例:https: //gist.github.com/1274607 (也在下面引用)

This way the composition root determines whether to hand out a single instance of MyModel(i.e. make it singleton scoped) or new ones for each class that requires it (instance scoped), or something in between. That logic belongs neither in the definition of MyModel, nor in the classes that ask for an instance of it.

通过这种方式,组合根确定是MyModel为每个需要它的类(实例范围)分发单个实例(即使其成为单例范围)还是新实例,或者介于两者之间。该逻辑既不属于 MyModel 的定义,也不属于要求其实例的类。

(Side note: although I haven't used it, wire.jsis a full-fledged dependency injection container for JavaScript that looks pretty cool.)

(旁注:虽然我没有用过它,wire.js是一个成熟的 JavaScript 依赖注入容器,看起来很酷。)



You are not necessarily abusing RequireJS by using it as you do, although what you are doing seems a bit roundabout, i.e. declaring a class than returning a new instance of it. Why not just do the following?

你不一定像你那样使用 RequireJS 来滥用它,尽管你正在做的事情似乎有点迂回,即声明一个类而不是返回它的一个新实例。为什么不做以下事情?

define(function () {
    var value = 10;

    return {
        doStuff: function () {
            alert(value);
        }
    };
});

The analogy you might be missing is that modules are equivalent to "namespaces" in most other languages, albeit namespaces you can attach functions and values to. (So more like Python than Java or C#.) They are not equivalent to classes, although as you have shown you can make a module's exports equal to those of a given class instance.

您可能遗漏的类比是,模块相当于大多数其他语言中的“命名空间”,尽管命名空间可以附加函数和值。(因此更像是 Python 而不是 Java 或 C#。)它们不等同于类,尽管正如您所展示的,您可以使模块的导出等于给定类实例的导出。

So you can create singletons by attaching functions and values directly to the module, but this is kind of like creating a singleton by using a static class: it is highly inflexible and generally not best practice. However, most people do treat their modules as "static classes," because properly architecting a system for dependency injection requires a lot of thought from the outset that is not really the norm in JavaScript.

因此,您可以通过将函数和值直接附加到模块来创建单例,但这有点像使用静态类创建单例:它非常不灵活,通常不是最佳实践。然而,大多数人确实将他们的模块视为“静态类”,因为正确构建依赖注入系统需要从一开始就进行大量思考,这在 JavaScript 中并不是真正的规范。



Here's https://gist.github.com/1274607inline:

这是https://gist.github.com/1274607内联:

// EntryPoint.js
define(function () {
    return function EntryPoint(model1, model2) {
        // stuff
    };
});

// Model1.js
define(function () {
    return function Model1() {
        // stuff
    };
});

// Model2.js
define(function () {
    return function Model2(helper) {
        // stuff
    };
});

// Helper.js
define(function () {
    return function Helper() {
        // stuff
    };
});

// composition root, probably your main module
define(function (require) {
    var EntryPoint = require("./EntryPoint");
    var Model1 = require("./Model1");
    var Model2 = require("./Model2");
    var Helper = require("./Helper");

    var entryPoint = new EntryPoint(new Model1(), new Model2(new Helper()));
    entryPoint.start();
});

回答by unscriptable

If you're serious about DI / IOC, you might be interested in wire.js: https://github.com/cujojs/wire

如果你对 DI / IOC 很认真,你可能会对 wire.js 感兴趣:https: //github.com/cujojs/wire

We use a combination of service relocation (like Domenic describes, but using curl.js instead of RequireJS) and DI (using wire.js). Service relocation comes in very handy when using mock objects in test harnesses. DI seems the best choice for most other use cases.

我们使用服务重定位(如 Domenic 描述的那样,但使​​用 curl.js 而不是 RequireJS)和 DI(使用 wire.js)的组合。在测试工具中使用模拟对象时,服务重定位非常方便。DI 似乎是大多数其他用例的最佳选择。

回答by widged

Not a singleton in a self-enforcing getInstance()-type singleton, but a context-enforced singleton (one instance per "context").

不是自执行 getInstance() 类型单例中的单例,而是上下文强制单例(每个“上下文”一个实例)。

I would recommend it only for static objects. It's perfectly fine to have a static object as a module that you load using in the require/define blocks. You then create a class with only static properties and functions. You then have the equivalent of the Math Object that has constants like PI, E, SQRT and functions like round(), random(), max(), min(). Great for creating Utility classes that can be injected at any time.

我只推荐它用于静态对象。将静态对象作为在 require/define 块中加载使用的模块非常好。然后创建一个只有静态属性和函数的类。然后,您就拥有了等价的数学对象,它具有 PI、E、SQRT 等常量和 round()、random()、max()、min() 等函数。非常适合创建可以随时注入的实用程序类。

Instead of this:

取而代之的是:

define(function() {
    var MyModel = function() {
        this.value = 10;
    }
    return new MyModel();
});

Which creates an instance, use the pattern for a static object (one where values are always the same as the Object never gets to be instantiated):

创建一个实例,使用静态对象的模式(一个值总是相同的对象永远不会被实例化):

define(function() {
    return {
       value: 10
    };
});

or

或者

define(function() {
    var CONSTANT = 10;
    return {
       value: CONSTANT
    };
});

If you want to pass an instance (the result of using a Module that have return new MyModel();), then, within an initialize function, pass a variable that capture the current state / context or pass on the Object that contains information on state / context that your modules needs to know about.

如果您想传递一个实例(使用具有 return new MyModel(); 的 Module 的结果),那么,在初始化函数中,传递一个捕获当前状态/上下文的变量或传递包含以下信息的对象您的模块需要了解的状态/上下文。