express实践
Node.js 7.0发布之前,写一篇关于express的文章
项目创建
使用express-generator
- 使用npm install express-generator -g
代码修改自动重启
使用nodemon
- nodemon ./bin/www
全局设置
1//加载配置项2global.Config = require(path.resolve(Root, './config/config'))3//通用方法(设置为全局对象,方便调用)4global.F = require(path.resolve(Root, './common/funcs'))5//socket事件方法6global.Socket = require(path.resolve(Root, './socket/socket'))7//加载所有的数据库model8global.M = {}9//model存储路径 (暂时不支持二级目录)10var modelsPath = path.resolve(Root, 'models')11fs.readdirSync(modelsPath).forEach(function (name) {12 if (path.extname(name) !== '') {13 name = path.basename(name, '.js')14 M[name] = require(path.resolve(modelsPath, name))15 }16})
使用co、Promise(bluebird)进行异步处理
定义通用方法run实行Promise,并抛出错误
1let run = (fn, next) => {2 co(fn).catch((err) => {3 next(err)4 })5}
通用方法列表 (大部分抄袭thinkjs)
1module.exports = {2 run: run,3 promisify: promisify,4 camelCase: camelCase,5 defer: defer,6 Class: Class,7 extend: extend,8 isClass: isClass,9 isBoolean: isBoolean,10 isNumber: isNumber,11 isObject: isObject,12 isString: isString,13 isArray: isArray,14 isFunction: isFunction,15 isDate: util.isDate,16 isRegExp: util.isRegExp,17 isError: util.isError,18 isIP: net.isIP,19 isIP4: net.isIPv4,20 isIP6: net.isIPv6,21 isFile: isFile,22 isFileAsync: isFileAsync,23 isDir: isDir,24 isDirAsync: isDirAsync,25 isNumberString: isNumberString,26 isPromise: isPromise,27 isWritable: isWritable,28 isBuffer: isBuffer,29 isTrueEmpty: isTrueEmpty,30 isEmpty: isEmpty,31 clone: clone,32 mkdir: mkdir,33 rmdir: rmdir,34 md5: md5,35 chmod: chmod,36 getFiles: getFiles,37 escapeHtml: escapeHtml,38 datetime: datetime,39 getDateTime: getDateTime,40 randomString: randomString,41}
数据库操作(mysql)
简单的数据库查询,没有封装sql(懒)
1var mysql = require('mysql')2var Promise = require('bluebird')3var dbConfig = Config.db45var pool = mysql.createPool(dbConfig)67//使用连接池8let query = (sql) => {9 return new Promise((resolve, reject) => {10 pool.getConnection((err, connection) => {11 connection.query(sql, function (err, result) {12 return err ? reject(err) : resolve(result)13 })14 connection.release()15 })16 })17}1819let insert = (table, data) => {20 return new Promise((resolve, reject) => {21 pool.getConnection((err, connection) => {22 connection.query(23 'INSERT INTO {table} SET ?',24 data,25 function (err, result) {26 return err ? reject(err) : resolve(result.insertId)27 }28 )29 connection.release()30 })31 })32}3334//普通连接35let queryTest = (sql) => {36 var connection = mysql.createConnection(dbConfig)37 return new Promise((resolve, reject) => {38 connection.connect()39 connection.query(sql, (err, rows, fields) => {40 return err ? reject(err) : resolve(rows)41 })42 connection.end()43 })44}4546module.exports = {47 query: query,48 queryTest: queryTest,49}
数据库连接测试代码 (使用了上面定义的run方法)
1router.get('/', function (req, res, next) {2 // 数据库操作测试3 F.run(function* () {4 var result = yield Db.query('SELECT * FROM fruitscities limit 5')5 var result = yield Db.query('SELECT * FROM fruitscities limit 5')6 req.session.admin = '111111111'7 console.log(req.session.admin)8 res.render('index', { title: 'Express```' })9 }, next)10})1112router.get('/test', function (req, res, next) {13 console.log(req.baseUrl)14 console.log(req.route)15 console.log(req.path)16 // 数据库操作测试17 F.run(function* () {18 var result = yield Db.query('SELECT * FROM fruitscities limit 5')19 var result = yield Db.query('SELECT * FROM fruitscities limit 5')20 console.log(req.session.admin)21 }, next)22})
使用nunjucks模板引擎
1//模板引擎2var nunjucks = require('nunjucks')3// 模板引擎设置4var env = new nunjucks.configure(path.join(__dirname, 'views'), {5 // 设置模板文件的目录,为views6 autoescape: true,7 watch: true,8 express: app,9})10app.set('view engine', 'html')
使用nunjucks模板标签(用于cms,文章,新闻展示等)
1//标签测试2var tags = require(path.resolve(Root, './common/tags'))34//绑定标签5env.addExtension('tagtest', new tags.tagtest())6common / tags.js中的代码78var tags9var nunjucks = require('nunjucks')10tags = {11 tagtest: function () {12 //tag标签测试13 this.tags = ['tagtest']14 this.parse = function (parser, nodes, lexer) {15 let tok = parser.nextToken()16 var args = parser.parseSignature(null, true)17 parser.advanceAfterBlockEnd(tok.value)18 let body = parser.parseUntilBlocks('endtagtest') // 结束标签19 parser.advanceAfterBlockEnd()20 //return new nodes.CallExtension(this, 'run', args);21 return new nodes.CallExtensionAsync(this, 'run', args, [body]) //异步调用22 }23 this.run = function (context, args, body, callback) {24 console.log(JSON.stringify(args)) //前台返回参数25 var data = [26 {27 id: 1,28 city: '北京',29 parent: 0,30 spelling: 'BeiJing',31 abbr: 'BJ',32 short: 'B',33 },34 {35 id: 2,36 city: '上海',37 parent: 0,38 spelling: 'ShangHai',39 abbr: 'SH',40 short: 'S',41 },42 {43 id: 3,44 city: '天津',45 parent: 0,46 spelling: 'TianJin',47 abbr: 'TJ',48 short: 'T',49 },50 {51 id: 4,52 city: '重庆',53 parent: 0,54 spelling: 'ZhongQing',55 abbr: 'ZQ',56 short: 'Z',57 },58 {59 id: 5,60 city: '黑龙江',61 parent: 0,62 spelling: 'HeiLongJiang',63 abbr: 'HLJ',64 short: 'H',65 },66 ]67 context.ctx['list'] = data //返回参数68 let result = new nunjucks.runtime.SafeString(body())69 return callback(null, result)70 }71 },72}7374module.exports = tags
页面中使用
1{% tagtest list="key1=1,key2=2,key3=3,key4=4" %}23 {% for val in list %}456 {{ val.id }}:{{ val.city}}789 {% endfor %}1011{% endtagtest %}121314{% tagtest key1=1,key2=2,key3=3,key4=4 %}1516 {% for val in list %}171819 {{ val.id }}:{{ val.city}}202122 {% endfor %}2324{% endtagtest %}
使用log4js进行日志记录
记录access日志
1app.use(log4js.connectLogger(log4js.getLogger('log_access'), { level: 'INFO' }))
配置文件 (配置可以根据需求修改)
1module.exports = {2 db: {3 host: '',4 user: '',5 password: '',6 database: '',7 },8 cookieSession: {9 name: 'session_uuice',10 keys: ['key1', 'key2'],11 secret: 'ksjf493248kjkj',12 },13 log4js: {14 appenders: [15 {16 type: 'console',17 category: 'console',18 },19 {20 category: 'log_file',21 type: 'file',22 filename: './logs/log_file/file.log',23 maxLogSize: 104800,24 backups: 100,25 },26 {27 category: 'log_date',28 type: 'dateFile',29 filename: './logs/log_date/date',30 alwaysIncludePattern: true,31 pattern: '-yyyy-MM-dd-hh.log',32 },33 {34 category: 'log_access',35 type: 'dateFile',36 filename: './logs/log_access/date',37 alwaysIncludePattern: true,38 pattern: '-yyyy-MM-dd-hh.log',39 },40 ],41 replaceConsole: true,42 levels: {43 log_file: 'ALL',44 console: 'ALL',45 log_date: 'ALL',46 },47 },48}
其他记录日志代码
1console.log('log_start start!')23var LogFile = log4js.getLogger('log_file')45LogFile.trace('This is a Log4js-Test')6LogFile.debug('We Write Logs with log4js')7LogFile.info('You can find logs-files in the log-dir')8LogFile.warn('log-dir is a configuration-item in the log4js.json')9LogFile.error("In This Test log-dir is : './logs/log_test/'")1011console.log('log_start end!')1213var log_date = log4js.getLogger('log_date')1415log_date.trace('This is a Log4js-Test')16log_date.debug('We Write Logs with log4js')17log_date.info('You can find logs-files in the log-dir')18log_date.warn('log-dir is a configuration-item in the log4js.json')19log_date.error("In This Test log-dir is : './logs/log_test/'")2021console.log('log_date end!')
socket通讯
使用socket.io 在项目bin/www中添加
1//添加socket.io支持2var io = require('socket.io')(server)3io.on('connection', function (socket) {4 Socket(socket, io) //这里的Socket,就是app.js定义的全局变量5})
在app.js中添加事件逻辑
1//socket事件方法2global.Socket = require(path.resolve(Root, './socket/socket'))
错误处理 Promise中的报错
1let run = (fn, next) => {2 co(fn).catch((err) => {3 next(err)4 })5}
其他报错
1// 将404交给错误处理中间件2app.use(function (req, res, next) {3 var err = new Error('Not Found')4 err.status = 4045 next(err)6})78// 错误处理910//开发环境报错,显示错误堆栈11if (app.get('env') === 'development') {12 app.use(function (err, req, res, next) {13 res.status(err.status || 500)14 if (req.xhr) {15 res.json({16 status: err.status,17 message: err.message,18 error: err.stack,19 })20 } else {21 res.render('error', {22 status: err.status,23 message: err.message,24 error: err,25 })26 }27 })28}2930//生产环境报错,不展示错误堆栈31app.use(function (err, req, res, next) {32 res.status(err.status || 500)33 if (req.xhr) {34 res.json({35 status: err.status,36 message: err.message,37 error: {},38 })39 } else {40 res.render('error', {41 status: err.status,42 message: err.message,43 error: {},44 })45 }46})
其他
待补充
暂无评论,来抢沙发吧。