如何向底层库提供数据库、记录器等依赖关系

How to provide dependencies like db, logger, etc to an underlying library?

本文关键字:数据库 记录器 关系 依赖      更新时间:2023-09-26

设置

我正在为分布式应用程序构建一个基础库。结构如下:

core_project/
    lib/
        index.js
        module1.js
        module2.js
        ...
    package.json

我的应用程序的许多其他部分将像这样使用这个库:

consumer_project/
    node_modules/
        core_project/
            ...
    app.js
    package.json

问题

我想要一些常见的依赖项,比如由使用者应用程序提供的DB处理程序。一旦初始化,我希望我的所有核心应用程序模块都能够使用这些依赖关系。

尝试的解决方案

我尝试在每个核心应用程序模块中创建模块初始化功能:core_project/lib/module1.js

var cfg = {db: null};
module.exports = {
    // ...
    'initModule': function (db) {
        cfg.db = db;
    }
}

这是我的核心模块索引文件:core_project/lib/index.js

var modules = {
    'module1': require('./module1'),
    'module1': require('./module2'),
    // ...
};
function create(db) {
    var app = {};
    init(app, modules, db);
    return app;
}
function init(app, mods, db) {
    var m;
    for (m in mods) {
        if (mods.hasOwnProperty(m)) {
            if (mods[m].hasOwnProperty('initModule')) {
                mods[m].initModule(db);
            }
            app[m] = mods[m];
        }
    }
}
module.exports = create;

现在,我的消费者应用程序可以传递这样的依赖项:consumer_project/app.js

var core = require('core_project');
var db = // initialize db
var app = core(db);
// Start using
app.module1.run();

尝试解决的问题

  1. 我必须添加cfg = {db: null}并导出initModule每个模块中需要依赖项的函数
  2. 我必须将每个模块附加到core_project/lib/index.js中的核心应用程序对象

问题

有没有更好的方法可以为核心库及其所有模块提供消费者提供的依赖关系,如数据库、记录器?

将依赖项作为参数传递(即依赖项注入(是实现这一点的一种非常有效的方法,尽管您可以使用闭包简化init:

core_project/lib/module1.js:

module.exports = function(db) {
  return function() {
    // closure scoped with dependencies
    // can use db object
  };
}

然后init函数将创建闭包:

app[m] = mods[m](db);

数据库客户端通常希望传递这样的dep,因此在整个模块中使用相同的连接,但其他类型的dep(如记录器(可能更适合使用模块系统的标准require()方法导入,例如require('winston')