【譯】 Node.js 中的依賴注入

引子

Dependency Injection 中瞭解了相關概念,接下來看看在 Node 中如何使用依賴注入。html

原文:Dependency Injection in Node.jsnode

正文

依賴注入是一種軟件設計模式,其中一個或多個依賴項(或服務)被注入或經過引用傳遞到依賴對象中。git

使用依賴注入的理由

解耦

依賴注入使你的模塊耦合性下降,從而產生更易於維護的代碼庫。github

便於單元測試

你能夠將它們傳遞到你想要使用的模塊中,而不是使用硬編碼的依賴項。在大多數狀況下,你沒必要使用 proxyquire 這樣的模塊。express

快速開發

使用依賴注入,定義接口以後,就能夠輕鬆地工做,不會出現任何合併衝突。npm

如何使用 Node.js 依賴注入

首先,讓咱們看看如何在不使用依賴注入的狀況下編寫你的應用程序,以及如何轉換它。設計模式

沒有使用依賴注入示例模塊

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

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

module.exports.getTeam = getTeam;

一個簡單的測試以下所示:api

// 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 方法,該方法返回一個用戶列表。session

看起來不錯,對吧?但在測試時,咱們必需要使用測試存根。app

在測試文件中,咱們還須要 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'
});

參考資料

相關文章
相關標籤/搜索