使用 Singleton 进行 Sequelize

jos*_*405 0 singleton node.js sequelize.js aws-lambda serverless-framework

我正在与Sequelizein合作node.js,想法是使用该Singleton模式。

阅读有关如何node使用模块缓存和一些单例示例的信息

我此时的文件是:

const DBManager = (function () {

  // Instance stores a reference to the Singleton
  let instance: any;

  let db: string = null;
  let user: string;
  let password: string;
  let host: string;
  let sequelize: Sequelize.Sequelize;

  function init(bdName: string) {
    db = bdName;
    user = process.env.MYSQL_DB_USERNAME || 'root';
    password = process.env.MYSQL_DB_PASSWORD || 'root';
    host = process.env.MYSQL_DB_HOST || 'localhost';

    return {
      open: () => {
        sequelize = new Sequelize(db, user, password, {
          host: host,
          dialect: 'mysql',
          pool: {
            max: 5,
            min: 0,
            acquire: 30000,
            idle: 10000
          },
          operatorsAliases: false,
          logging: !process.env.HIDE_LOGS
        });
      },

      testConnection: () => {
        return sequelize.authenticate();
      },

      getManagerObject: () => {
        return sequelize;
      },

      close: () => {
        sequelize.close();
      }
    };
  }

  return {
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: (bd?: string) => {

      if (!instance) {
        instance = init(bd);
      }

      return instance;
    }
  };

})();

export default DBManager;
Run Code Online (Sandbox Code Playgroud)

因此,正如预期的那样,当我在项目中的任何位置需要此文件时,引用是相同的并且按预期工作。

我不确定这是否是实现 的正确方法Singleton pattern,或者是否有定义和记录的方法,因为官方文档对此没有任何说明。

Est*_*ask 6

通常不需要显式的单例实现。JS 模块(特别是 CommonJS 和 ES 模块)在正常情况下仅评估一次,导出的类实例实际上是单例。

也不需要 IIFE,因为模块有自己的作用域。由于init函数没有被重用,因此可能也不需要它。可以简化为:

export default {
  open: ...
  testConnection: ...
  ...
};
Run Code Online (Sandbox Code Playgroud)

这种抽象并不实用。已经有sequelize实例了,为自己的方法创建包装方法并没有什么好处。

由于连接在建立后即可使用,因此仅导出连接的承诺是有意义的,类似于此答案中所示的连接中所示的连接。

如果配置(数据库名称)在数据库管理器模块中可用,最好就地使用它:

// db.js
const dbName = someConfig.db;
const sequelize = new Sequelize(dbName, ...);

export default sequelize.authenticate().then(() => sequelize);
Run Code Online (Sandbox Code Playgroud)

其用法如下:

import dbConnection from './db';

dbConnection.then(sequelize => { /* all code that depends on the connection */ });
Run Code Online (Sandbox Code Playgroud)

如果可能有多个连接,或者导入时配置不可用,则会导出工厂函数:

// db.js
export default dbName => {
  const sequelize = new Sequelize(dbName, ...);
  sequelize.authenticate().then(() => sequelize);
}
Run Code Online (Sandbox Code Playgroud)

单例实例自然是用模块处理的:

// foo-db.js
import getDbConnection from './db';

export default getFooDbName().then(dbName => getDbConnection(dbName));
Run Code Online (Sandbox Code Playgroud)

并使用如下:

import dbConnection from './foo-db';

dbConnection.then(sequelize => { /* all code that depends on the connection */ });
Run Code Online (Sandbox Code Playgroud)