4

【译】 Node.js 中的依赖注入

 3 years ago
source link: https://segmentfault.com/a/1190000040172057
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Dependency Injection 中了解了相关概念,接下来看看在 Node 中如何使用依赖注入。

原文:Dependency Injection in Node.js

依赖注入是一种软件设计模式,其中一个或多个依赖项(或服务)被注入或通过引用传递到依赖对象中。

使用依赖注入的理由

依赖注入使你的模块耦合性降低,从而产生更易于维护的代码库。

便于单元测试

你可以将它们传递到你想要使用的模块中,而不是使用硬编码的依赖项。在大多数情况下,你不必使用 proxyquire 这样的模块。

使用依赖注入,定义接口之后,就可以轻松地工作,不会出现任何合并冲突。

如何使用 Node.js 依赖注入

首先,让我们看看如何在不使用依赖注入的情况下编写你的应用程序,以及如何转换它。

没有使用依赖注入示例模块

// team.js
var User = require('./user');

function getTeam(teamId) {
  return User.find({teamId: teamId});
}

module.exports.getTeam = getTeam;

一个简单的测试如下所示:

// team.spec.js
var Team = require('./team');
var User = require('./user');

describe('Team', function() {
  it('#getTeam', function* () {
    var users = [{id: 1, id: 2}];

    this.sandbox.stub(User, 'find', function() {
      return Promise.resolve(users);
    });

    var team = yield team.getTeam();

    expect(team).to.eql(users);
  });
});

我们在这里所做的是创建了一个名为 team.js 的文件,它可以返回属于单个团队的用户列表。为此,我们需要 User 模型,因此我们可以调用它的 find 方法,该方法返回一个用户列表。

看起来不错,对吧?但在测试时,我们必须要使用测试存根。

在测试文件中,我们还需要 require User 模型,这样就可以存根它的 find 方法。请注意,我们在这里使用的是沙盒特性,因此不必在测试运行后手动恢复原始函数。

使用依赖注入示例模块

// team.js
function Team(options) {
  this.options = options;
}

Team.prototype.getTeam = function(teamId) {
  return this.options.User.find({teamId: teamId})
}

function create(options) {
  return new Team(options);
}

你可以使用以下测试用例测试此文件:

// team.spec.js
var Team = require('./team');

describe('Team', function() {
  it('#getTeam', function* () {
    var users = [{id: 1, id: 2}];

    var fakeUser = {
      find: function() {
        return Promise.resolve(users);
      }
    };

    var team = Team.create({
      User: fakeUser
    });

    var team = yield team.getTeam();

    expect(team).to.eql(users);
  });
});

好的,那么依赖注入的版本和上一个版本有何不同呢?你可以注意到的第一件事是工厂模式的使用:我们使用它向新创建的对象注入选项/依赖项—这是我们可以注入 User 模型的地方。

在测试文件中,我们必须创建一个表示 User 模型的假模型,然后我们只需通过将其传递给 Team 模型的 create 函数来注入这个模型。很简单,对吧?

在实际项目中的依赖注入

你可以在很多开源项目中找到依赖注入的例子。例如,你在日常工作中使用的大多数 Express/Koa 中间件都使用相同的方法。

Express 中间件

var express = require('express');
var app = express();
var session = require('express-session');

app.use(session({
  store: require('connect-session-knex')()
}));

上面的代码片段使用工厂模式的依赖注入:向 session 中间件传递 connect-session-knex 模块-它必须实现一个接口,session 模块将调用该接口。

在这个示例中,connect-session-knex 模块必须实现以下方法:

  • store.destroy(sid, callback)
  • store.get(sid, callback)
  • store.set(sid, session, callback)

Hapi 插件

同样的概念也可以在 Hapi 中找到-下面的示例将 handlebars 模块作为视图引擎注入 Hapi 中使用。

server.views({
  engines: {
    html: require('handlebars')
  },
  relativeTo: __dirname,
  path: 'templates'
});

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK