storage
. We will foresee the possibility of using one of several types of storage, for example, FsStorage
(file storage), MysqlStorage
(MySQL storage), MongoStorage
(Mongo storage).package.json
: { "name": "storage", "version": "0.1.0", "main": "./lib/index.js", "dependencies": { "mysql": "*", "mongoose": "*" } }
lib/index.js
: module.exports = { FsStorage: require('./fs-storage.jsx'), MysqlStorage: require('./mysql-storage.jsx'), MongoStorage: require('./mongo-storage.jsx') };
lib/fs-storage.js
: var fs = require('fs'); module.exports = FsStorage; function FsStorage() { // init code... }
lib/mysql-storage.js
: var mysql = require('mysql'); module.exports = MysqlStorage; function MysqlStorage() { // init code... }
lib/mongo-storage.js
: var mongoose = require('mongoose'); module.exports = MongoStorage; function MongoStorage() { // init code... }
mysql
and mongoose
is not necessary for the demonstration. Therefore, let's place mysql
and mongoose
stubs (under the spoiler) instead of the code:node_modules/mysql/index.js
: console.log('MySQL module loaded');
node_modules/mongoose/index.js
: console.log('Mongoose module loaded');
storage/ ├ lib/ │ ├ index.js │ ├ fs-storage.js │ ├ mongo-storage.js │ └ mysql-storage.js ├ node_modules/ │ ├ mongoose/ │ │ └ index.js │ └ mysql/ │ └ index.js └ package.json
var storage = require('storage'); var fsStorage = new storage.FsStorage();
require('storage')
, messages are displayed in the console: MySQL module loaded Mongoose module loaded
Object.defineProperty()
experimented with the Object.defineProperty()
method, I achieved an amazing result, which I designed as a function demandProperty()
: function demandProperty(obj, name, modPath) { Object.defineProperty(obj, name, { configurable: true, enumerable: true, get: function() { var mod = require(modPath); Object.defineProperty(obj, name, { configurable: false, enumerable: true, value: mod }); return mod } }) }
MysqlStorage()
, an accessor ( getter ) is created. With any request to the accessor, require()
triggered, and the accessor itself returns the result of require()
. In addition, using the same Object.defineProperty()
we set back a direct link to the same require()
result instead of the accessor (that is, on MysqlStorage()
). So all requests (of course, except the first) will work with the same speed and reliability from leaks, as if we had left the classic require()
.lib/index.js
. Replace: module.exports = { FsStorage: require('./fs-storage.jsx'), MysqlStorage: require('./mysql-storage.jsx'), MongoStorage: require('./mongo-storage.jsx'), };
on: demandProperty(module.exports, 'FsStorage', './fs-storage.jsx'); demandProperty(module.exports, 'MysqlStorage', './mysql-storage.jsx'); demandProperty(module.exports, 'MongoStorage', './mongo-storage.jsx');
var storage = require('storage'); console.log(util.inspect(storage)); /* => { FsStorage: [Getter], MysqlStorage: [Getter], MongoStorage: [Getter] } */ console.log(util.inspect(storage.FsStorage.name)); // => 'FsStorage' console.log(util.inspect(storage)); /* => { FsStorage: [Function: FsStorage], MysqlStorage: [Getter], MongoStorage: [Getter] } */ var mysql = new storage.MysqlStorage(); // => MySQL module loaded console.log(util.inspect(mysql)); // => '{}' console.log(util.inspect(storage)); /* => { FsStorage: [Function: FsStorage], MysqlStorage: [Function: MysqlStorage], MongoStorage: [Getter] } */
demandProperty()
function is demandProperty()
outside the modules in the lib
folder, the last argument must be passed the full path to the module, otherwise require()
will look for the module in the folder where demandProperty()
defined: demandProperty(module.exports, 'FsStorage', path.resolve(__dirname, './fs-storage.jsx')); demandProperty(module.exports, 'MysqlStorage', path.resolve(__dirname, './mysql-storage.jsx')); demandProperty(module.exports, 'MongoStorage', path.resolve(__dirname, './mongo-storage.jsx'));
Source: https://habr.com/ru/post/259281/
All Articles