1. 程式人生 > 其它 >【譯】 Node.js 中的依賴注入

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

目錄

引子

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'
});
Back to top

參考資料