与Singleton续集

时间:2018-07-18 16:02:55

标签: node.js aws-lambda singleton sequelize.js serverless-framework

我正在Sequelize中使用node.js,其想法是使用Singleton模式。

了解nodemodules caching的工作方式以及一些单例示例

此刻我的文件是:

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;

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

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

1 个答案:

答案 0 :(得分:2)

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

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

export default {
  open: ...
  testConnection: ...
  ...
};

这种抽象是不实际的。已经有sequelize个实例,为其自己的方法创建包装器方法并没有什么用。

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

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

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

export default sequelize.authenticate().then(() => sequelize);

其用法类似于:

import dbConnection from './db';

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

如果可能存在多个连接,或者导入时配置不可用,则将导出工厂功能:

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

单个实例自然由模块处理:

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

export default getFooDbName().then(dbName => getDbConnection(dbName));

并按如下方式使用:

import dbConnection from './foo-db';

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