轻盈的鱼

← 返回归档

express实践

日期:2017/04/29分类:nodejs

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//加载所有的数据库model
8global.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.db
4
5var pool = mysql.createPool(dbConfig)
6
7//使用连接池
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}
18
19let 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}
33
34//普通连接
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}
45
46module.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})
11
12router.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 // 设置模板文件的目录,为views
6 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'))
3
4//绑定标签
5env.addExtension('tagtest', new tags.tagtest())
6common / tags.js中的代码
7
8var tags
9var 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}
73
74module.exports = tags

页面中使用

1{% tagtest list="key1=1,key2=2,key3=3,key4=4" %}
2
3 {% for val in list %}
4
5
6 {{ val.id }}:{{ val.city}}
7
8
9 {% endfor %}
10
11{% endtagtest %}
12
13
14{% tagtest key1=1,key2=2,key3=3,key4=4 %}
15
16 {% for val in list %}
17
18
19 {{ val.id }}:{{ val.city}}
20
21
22 {% endfor %}
23
24{% 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!')
2
3var LogFile = log4js.getLogger('log_file')
4
5LogFile.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/'")
10
11console.log('log_start end!')
12
13var log_date = log4js.getLogger('log_date')
14
15log_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/'")
20
21console.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 = 404
5 next(err)
6})
7
8// 错误处理
9
10//开发环境报错,显示错误堆栈
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}
29
30//生产环境报错,不展示错误堆栈
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})

其他

待补充

版权信息

日期2017/04/29
协议CC BY-NC-SA 4.0 转载请注明出处
评论

暂无评论,来抢沙发吧。

返回顶部