// config.js exports.port = 8080; // app.js var express = require('express'); var config = require('./config.js'); var app = express(); app.get('/hello', function(req, res) { res.end('Hello world'); }); app.listen(config.port);  // config.js exports.port = 8080; exports.mongoUrl = 'mongodb://localhost:27017/test'; // app.js var express = require('express'); var MongoClient = require('mongodb').MongoClient; var config = require('./config.js'); //     var db; MongoClient.connect(config.mongoUrl, function(err, client){ if (err) { console.error(err); process.exit(1); } db = client; }); //  - var app = express(); app.get('/', function(req, res, next) { db.collection('files').find({}).toArray(function(err, list){ if (err) return next(err); res.type('text/plain').end(list.map(function(file){ return file.path; }).join('\r')); }); }); app.get('/file', function(req, res, next){ db.collection('files').findOne({path:req.query.file}).toArray(function(err, file){ if (err) return next(err); res.type('text/plain').end(file.content); }); }); app.listen(config.port); Ok, everything is simple and clear: connect to the base, create a server, assign handles for the paths. But let's think about what disadvantages the code has: // app.js var MongoClient = require('mongodb').MongoClient; var EventEmitter = require('event').EventEmitter; var util = require('util'); module.exports = App; function App(config) { var self = this; //  event emitter EventEmitter.call(this); MongoClient.connect(config.mongoUrl, function(err, db){ if (err) return self.emit("error", err); self.db = db; }); this.list = function(callback) { self.db .collection('files') .find({}) .toArray(function(err, files){ if (err) return callback(err); files = files.map(function(file){ return file.path }); callback(null, files); }); }; this.file = function(file, callback) { self.db .collection('files') .findOne({path:file}) .toArray(callback); }; } util.inherits(App, EventEmitter); // config.js exports.mongoUrl = "mongo://localhost:27017/test"; exports.http = { port : 8080 }; // http.js var App = require('./app.js'); var express = require('express'); var configPath = process.argv[2] || process.env.APP_CONFIG_PATH || './config.js'; var config = require(configPath); var app = new App(config); app.on("error", function(err){ console.error(err); process.exit(1); }); var server = express(); server.get('/', function(req, res, next){ app.list(function(err, files){ if (err) return next(err); res.type('text/plain').end(files.join('\n')); }); }); server.get('/file', function(req, res, next){ app.file(req.query.file, function(err, file){ if (err) return next(err); res.type('text/plain').end(file); }); }); server.listen(config.http.port); What have we done? Added event model for catching errors. Added the ability to specify the configuration path for each application instance. // cli.js var App = require('./app.js'); var program = require('commander'); var app; program .version('0.1.0') .option('-c, --config <file>', 'Config path', 'config.js', function(configPath){ var config = require(configPath); app = new App(config); app.on("error", function(err){ console.error(err); process.exit(1); }); }); program.command('list') .description('List files') .action(function(){ app.list(function(err, files){ if (err) return app.emit("error", err); console.log(files.join('\n')); }); }); program.command('print <file>') .description('Print file content') .action(function(cmd){ app.file(cmd.file, function(err, file){ if (err) return app.emit("error", err); console.log(file); }); }); or test // test.js var App = require('App'); var app = new App({ mongoUrl : "mongo://testhost:27017/test" }); //       : // {path:'README.md', content:'This is README.md'} app.on("error", function(err){ console.error('Test failed', err); process.exit(1); }); //     nodeunit module.exports = { "Test file list":function(test) { app.list(function(err, files){ test.ok(Array.isArray(files), "Files is an Array."); test.equals(files.length, 1, "Files length is 1."); test.equals(file[0], "README.md", "Filename is 'README.md'."); test.done(); }); } } Of course, the application now does not look as minimalistic as in the examples, but it is more flexible. In the next part I will tell about catching errors.Source: https://habr.com/ru/post/241788/
All Articles