【譯】 Node.js 中的依賴注入
目錄
引子
在 Dependency Injection 中瞭解了相關概念,接下來看看在 Node 中如何使用依賴注入。
原文:Dependency Injection in Node.js
正文
依賴注入是一種軟體設計模式,其中一個或多個依賴項(或服務)被注入或通過引用傳遞到依賴物件中。
使用依賴注入的理由
解耦
依賴注入使你的模組耦合性降低,從而產生更易於維護的程式碼庫。
便於單元測試
你可以將它們傳遞到你想要使用的模組中,而不是使用硬編碼的依賴項。在大多數情況下,你不必使用
快速開發
使用依賴注入,定義介面之後,就可以輕鬆地工作,不會出現任何合併衝突。
如何使用 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