express后续篇
模板引擎
在 Express 中使用模板引擎
需要在应用中设置模板文件目录views,设置模板引擎view engine * views, 放模板文件的目录,比如: app.set('views', './views') * view engine, 模板引擎,比如: app.set('view engine', 'jade')
如上例,我们用了jade模板语言,那么我们对应的需要npm相关的软件包 1
npm install jade --save
和 Express 兼容的模板引擎,比如 Jade,通过 res.render() 调用其导出方法 __express(filePath, options, callback) 渲染模板。
有一些模板引擎不遵循这种约定,Consolidate.js 能将 Node 中所有流行的模板引擎映射为这种约定,这样就可以和 Express 无缝衔接。
一旦 view engine 设置成功,就不需要显式指定引擎,或者在应用中加载模板引擎模块,Express 已经在内部加载,如下所示。 1
app.set('view engine', 'jade');
现在我们在views目录下创建名字为index.jade的Jade模板文件,内容如下: 1
2
3
4
5html
head
title!= title
body
h1!= message
然后创建一个路由来渲染index.jade文件。如果没有设置 view engine,您需要指明视图文件的后缀,否则就会遗漏它。 1
2
3app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: 'Hello there!'});
});
此时向主页发送请求,“index.jade” 会被渲染为 HTML。
错误处理
错误处理的函数形式相当于其他的中间件的callback(req, res, next)
,它需要四个参数(err, req, res, next)
,例如: 1
2
3
4app.use(function(err, req, res, next) {
console.error(error.stack)
res.status(500).send('Something broke!')
})
它的位置则在app.use()
和路由调用后,最后定义错误处理中间件,比如: 1
2
3
4
5
6
7
8
9var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(bodyParser());
app.use(methodOverride());
// ...路由
app.use(function(err, req, res, next) {
// 业务逻辑
})
为了便于组织,可能会想定义常规中间件一样定制多个错误处理中间件,加强项目的逻辑性。
比如你想为使用XHR的请求定义一个,还想为没有使用的定义一个,那么: 1
2
3
4
5
6
7
8var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(bodyParser());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHndler);
logErrors会将请求和错误信息写入标准错误输出、日志或类似服务: 1
2
3
4function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}1
2
3
4
5
6
7function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something blew up!' });
} else {
next(err);
}
}
errorHandler 能捕获所有错误,其定义如下: 1
2
3
4function errorHandler(err, req, res, next) {
res.status(500);
res.render('error', { error: err });
}
错误处理的next() 传入参数(除了 ‘route’ 字符串),express会认为当前请求有错误的输出,会跳到下一个错误处理的中间件。
如下节所示。
如果路由句柄有多个回调函数,可使用 ‘route’ 参数跳到下一个路由句柄。比如:
1 | app.get('/a_route_behind_paywall', |
在这个例子中,句柄 getPaidContent 会被跳过,但 app 中为 /a_route_behind_paywall 定义的其他句柄则会继续执行。
next() 和 next(err) 类似于 Promise.resolve() 和 Promise.reject()。它们让您可以向 Express 发信号,告诉它当前句柄执行结束并且处于什么状态。next(err) 会跳过后续句柄,除了那些用来处理错误的句柄。
缺省错误处理句柄
Express 内置了一个错误处理句柄,它可以捕获应用中可能出现的任意错误。这个缺省的错误处理中间件将被添加到中间件堆栈的底部。
如果你向 next() 传递了一个 error ,而你并没有在错误处理句柄中处理这个 error,Express 内置的缺省错误处理句柄就是最后兜底的。最后错误将被连同堆栈追踪信息一同反馈到客户端。堆栈追踪信息并不会在生产环境中反馈到客户端。
设置环境变量 NODE_ENV 为 “production” 就可以让应用运行在生产环境模式下。
如果你已经开始向 response 输出数据了,这时才调用 next() 并传递了一个 error,比如你在将向客户端输出数据流时遇到一个错误,Express 内置的缺省错误处理句柄将帮你关闭连接并告知 request 请求失败。
因此,当你添加了一个自定义的错误处理句柄后,如果已经向客户端发送包头信息了,你还可以将错误处理交给 Express 内置的错误处理机制。
1 | function errorHandler(err, req, res, next) { |
调试 Express
Express 内部使用 debug 模块记录路由匹配、使用到的中间件、应用模式以及请求-响应循环。
debug 有点像改装过的 console.log,不同的是,您不需要在生产代码中注释掉 debug。它会默认关闭,而且使用一个名为 DEBUG 的环境变量还可以打开。
在启动应用时,设置 DEBUG 环境变量为 express:*,可以查看 Express 中用到的所有内部日志。 1
DEBUG=express:* node index.js
在由 express 应用生成器 生成的默认应用中执行,会打印出如下信息: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25> test-express@1.0.0 test /home/hdd/练习/express
> node app.js
express:application set "x-powered-by" to true +0ms
express:application set "etag" to 'weak' +4ms
express:application set "etag fn" to [Function:generateETag] +1ms
express:application set "env" to 'development' +1ms
express:application set "query parser" to 'extended' +0ms
express:application set "query parser fn" to [Function: parseExtendedQueryString] +0ms
express:application set "subdomain offset" to 2+0ms
express:application set "trust proxy" to false +0ms
express:application set "trust proxy fn" to [Function: trustNone] +1ms
express:application booting in development mode+0ms
express:application set "view" to [Function: View] +0ms
express:application set "views" to '/home/hdd/练习/express/views' +0ms
express:application set "jsonp callback name" to 'callback' +0ms
express:application set "view engine" to 'jade'+0ms
express:router use '/' query +1ms
express:router:layer new '/' +0ms
express:router use '/' expressInit +1ms
express:router:layer new '/' +0ms
express:router:route new '/' +0ms
express:router:layer new '/' +0ms
express:router:route get '/' +1ms
express:router:layer new '/' +0ms
当应用收到请求时,能看到Express代码中打印出的日志。 1
2
3
4
5
6
7
8
9
10express:router dispatching GET / +5s
express:router query : / +1ms
express:router expressInit : / +1ms
express:view require "jade" +2ms
express:view lookup "index.jade" +564ms
express:view stat "/home/hdd/练习/express/views/index.jade" +1ms
express:view render "/home/hdd/练习/express/views/index.jade" +0ms
express:router dispatching GET /favicon.ico +245ms
express:router query : /favicon.ico +0ms
express:router expressInit : /favicon.ico +1ms
通过 express 生成应用
将命名空间限制其中 需要添加DEBUG=ITEM-NAME
详见 调试指南
数据库集成
为 Express 应用添加连接数据库的能力,只需要加载相应数据库的 Node.js 驱动即可。
介绍下常见数据库驱动 * Cassandra * CouchDB * LevelDB * MySQL * MongoDB * Neo4j * PostgreSQL * Redis * SQLite * ElasticSearch
- 本文标题:express后续篇
- 本文作者:hddhyq
- 本文链接:https://hddhyq.github.io/2017/11/12/express后续篇/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!