我目前正在用nodejs创建一些实验性项目。我用Spring编写过很多Java EE web应用程序,非常欣赏依赖注入的便利性。

现在我很好奇:如何对节点进行依赖注入?或者:我真的需要它吗?因为编程风格不同,是否存在替代概念?

到目前为止,我谈论的是一些简单的事情,比如共享数据库连接对象,但我还没有找到一个让我满意的解决方案。


当前回答

我开发了一个库,用一种简单的方式处理依赖注入,减少了样板代码。每个模块由唯一的名称和控制器函数定义。控制器的参数反映了模块的依赖关系。

阅读更多关于KlarkJS的内容

简单的例子:

KlarkModule(module, 'myModuleName1', function($nodeModule1, myModuleName2) {
    return {
        log: function() { console.log('Hello from module myModuleName1') }
    };
});

myModuleName1是模块的名称。 $nodeModule1是node_module的一个外部库。名称解析为node-module1。前缀$表示它是一个外部模块。 myModuleName2是一个内部模块的名称。 控制器的返回值来自其他内部模块,当它们定义参数myModuleName1时。

其他回答

TypeDI是这里提到的最可爱的,看看TypeDI中的代码

import "reflect-metadata";
import {Service, Container} from "typedi";

@Service()
class SomeClass {

    someMethod() {
    }

}

let someClass = Container.get(SomeClass);
someClass.someMethod();

看看这段代码:

import {Container, Service, Inject} from "typedi";

// somewhere in your global app parameters
Container.set("authorization-token", "RVT9rVjSVN");

@Service()
class UserRepository {

    @Inject("authorization-token")
    authorizationToken: string;

}

我最近创建了一个名为circuitbox的库,它允许你在node.js中使用依赖注入。与我见过的许多基于依赖项查找的库相比,它实现了真正的依赖项注入。Circuitbox还支持异步创建和初始化例程。下面是一个例子:

假设下面的代码位于名为consoleMessagePrinter.js的文件中

'use strict';

// Our console message printer
// deps is injected by circuitbox with the dependencies
function ConsoleMessagePrinter(deps) {
  return {
    print: function () {
      console.log(deps.messageSource.message());
    }
  };
}

module.exports = ConsoleMessagePrinter;

假设main.js文件中包含以下内容

'use strict';

// our simple message source
// deps is injected by circuitbox with the dependencies
var simpleMessageSource = function (deps) {
  return {
    message: function () {
      return deps.message;
    }
  };
};

// require circuitbox
var circuitbox = require('../lib');

// create a circuitbox
circuitbox.create({
  modules: [
    function (registry) {
      // the message to be used
      registry.for('message').use('This is the message');

      // define the message source
      registry.for('messageSource').use(simpleMessageSource)
        .dependsOn('message');

      // define the message printer - does a module.require internally
      registry.for('messagePrinter').requires('./consoleMessagePrinter')
        .dependsOn('messageSource');
    }
  ]
}).done(function (cbx) {

  // get the message printer and print a message
  cbx.get('messagePrinter').done(function (printer) {
    printer.print();
  }, function (err) {
    console.log('Could not recieve a printer');
    return;
  });

}, function (err) {
  console.log('Could not create circuitbox');
});

Circuitbox允许您定义组件并将它们的依赖项声明为模块。一旦初始化,它允许您检索组件。Circuitbox自动注入目标组件所需的所有组件,并将其提供给您使用。

该项目处于alpha版本。欢迎您的评论、想法和反馈。

希望能有所帮助!

这取决于应用程序的设计。显然,你可以做一个类似java的注入,在那里创建一个类的对象,并将依赖项传递给构造函数,就像这样。

function Cache(store) {
   this._store = store;
}

var cache = new Cache(mysqlStore);

如果你不是在javascript中做OOP,你可以做一个init函数来设置一切。

然而,还有另一种方法可以采用,这种方法在基于事件的系统(如node.js)中更为常见。如果您可以将应用程序建模为仅(大多数时候)对事件进行操作,那么您所需要做的就是设置所有内容(我通常通过调用init函数来完成)并从存根发出事件。这使得测试相当容易和易读。

它应该像这样灵活和简单:

var MyClass1 = function () {}
var MyClass2 = function (myService1) {
    // myService1.should.be.instanceof(MyClass1); 
}


container.register('myService1', MyClass1);
container.register('myService2', MyClass2, ['myService1']);

我写过一篇关于node.js中的依赖注入的文章。

管理你的服务-node.js依赖注入 包文档在这里

我希望它能帮到你。

对于ES6,我开发了这个容器 https://github.com/zazoomauro/node-dependency-injection

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container.register('mailer', 'Mailer')

然后,您可以设置,例如,在集装箱中的运输选择:

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container
  .register('mailer', 'Mailer')
  .addArgument('sendmail')

这个类现在灵活得多,因为您已经将传输的选择从实现中分离出来,并将其放入容器中。

现在邮件服务已经在容器中,您可以将其作为其他类的依赖项注入。如果你有一个这样的newsletter ttermanager类:

class NewsletterManager {
    construct (mailer, fs) {
        this._mailer = mailer
        this._fs = fs
    }
}

export default NewsletterManager

在定义newsletter tter_manager服务时,邮件服务还不存在。使用Reference类告诉容器在初始化通讯管理器时注入mailer服务:

import {ContainerBuilder, Reference, PackageReference} from 'node-dependency-injection'
import Mailer from './Mailer'
import NewsletterManager from './NewsletterManager'

let container = new ContainerBuilder()

container
  .register('mailer', Mailer)
  .addArgument('sendmail')

container
  .register('newsletter_manager', NewsletterManager)
  .addArgument(new Reference('mailer'))
  .addArgument(new PackageReference('fs-extra'))

你也可以用Yaml、Json或JS文件等配置文件来设置容器

由于各种原因,可以编译服务容器。这些原因包括检查任何潜在的问题,如循环引用和使容器更高效。

container.compile()