Express学习之指南<2>

三.使用模版引擎

在Express能够渲染模版文件之前,必须要对应用进行下面的设置:

  • views:模版文件所在的目录,例如:app.set('views', './views')
  • view engine:指定使用的模版引擎,例如:app.set('view engine', 'jade')

然后安装对应的模版引擎包:

$ npm install jade --save

能够迎合Express模版引擎(例如Jade),都会导出一个函数__express(filePath, options, callback),这个函数会被res.render()调用来渲染模版代码。

一些模版引擎不遵守这个约定, Consolidate.js 这个库可以让所有的nodejs模版引擎遵守这个约定,这样就能让这些模版引擎在Express中工作。

一旦设置了view engine(视图引擎),你就不必在你的应用中显式地声明模版或者加载模版引擎模块。Express会在应用中自动加载:

app.set('view engine', 'jade');

views(视图目录)中创建一个Jade模版文件,命名为index.jade,内容如下:

html
  head
    title!= title
  body
    h1!= message

然后创建一个路由来渲染index.jade文件,如果view engine(视图引擎)属性没有设置的话,你必须要声明视图文件的扩展。

app.get('/', function (req, res) {
  res.render('index', { title: 'Hey', message: 'Hello there!'});
});

一旦对主页发送请求的话,index.jade就会被渲染成HTML。

为了更好地理解Express中模版引擎如何工作的,请阅读为Express开发模版引擎

四.错误处理

定义处理错误的中间件和定义其它中间件一样,只不过它有四个参数,而不是三个,函数签名是(err, req, res, next)。

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

你要在最后定义错误处理的中间件,要放在app.use()和路由调用之后,例如:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(function(err, req, res, next) {
  // logic
});

来自错误处理的中间件的响应是完全随意的,你可以返回一个HTML处理页面,一个简单的信息,一个JSON字符串,或者其它你想要设置的。

处于组织化的目的,你可能会定义几个错误处理的中间件。例如,你想定义一个错误处理器,负责处理通过XHR(XMLHttpRequest)发送的请求。

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

方法logErrors可能会将请求和错误消息写到stderr,或其他相似的服务中。

function logErrors(err, req, res, next) {
  console.error(err.stack);
  next(err);
}

clientErrorHandler方法像下面这样定义,注意错误被显式地传到next中。

function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something blew up!' });
  } else {
    next(err);
  }
}

下面的errorHandler方法定义:

function errorHandler(err, req, res, next) {
  res.status(500);
  res.render('error', { error: err });
}

如果你传递一些参数(除了字符串'route')给next()函数的话,Express会把当前的请求当作有错误发生,会跳过任何剩下来的路由/中间件函数。如果你想要以某种方式处理所发生的错误的话,你必须要创建一个处理错误的路由。

如果你有一个包含多个回调函数的路由处理器的话,你可以使用route这个参数来跳过剩下的部分直接来到下一个路由处理器。

app.get('/a_route_behind_paywall', 
  function checkIfPaidSubscriber(req, res, next) {
    if(!req.user.hasPaid) { 

      // continue handling this request 
      next('route');
    }
  }, function getPaidContent(req, res, next) {
    PaidContent.find(function(err, doc) {
      if(err) return next(err);
      res.json(doc);
    });
  });

在这个例子中,getPaidContent这个处理器会被跳过,但是应用中剩下的对于路径/a_route_behind_paywall的处理器都会被执行。

调用next()next(err)表明当前的处理器是完整的,next(err)会跳过所有剩下的处理器,除了那些被用来处理错误的处理器。

默认的错误处理器:

Express自身携带一个内置的错误处理器,它将负责处理发生在应用中的任何错误,这个默认的错误处理的中间件被放在中间件栈底。

如果你传递一个错误给next(),你没有在一个错误处理器中处理这个错误,这个错误将会由Express内置的错误处理器负责处理。这个错误会连同堆栈轨迹一同写进客户端。堆栈轨迹不会包含在生产环境中。

讲解:设置环境变量NODE_ENV的值为production,来让应用运行于生产模式中。

如果在你已经写了响应之后,调用包含一个错误的next()函数,Express默认的错误处理器将会关掉连接,让这个请求被认为是失败的。

所以当你增加一个自定义的错误处理器的时候,你将想要委托给Express中的默认错误处理机制,尽管响应的头部已经发送给了客户端。

function errorHandler(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}

五.调试Express

Express使用debug这个模块来一步步地打印出关于路由匹配,使用的中间件,应用模式和request-response循环流的相关信息。

debug就像是console.log的一个加强版本,但它不像console.log,你不必再生产模式下注释掉debug的打印日志。生产环境下它会被默认关闭掉,如果你可以设置环境变量DEBUG来自由地控制。

为了看到Express内部使用的所有打印记录,当你启动应用的时候,设置环境变量DEBUG的值为:express:*

$ DEBUG=express:* node index.js

在Windows平台上,使用对应的命令:

> set DEBUG=express:* & node index.js

express generator创建的默认应用中运行下面命令,将会打印出:

$ DEBUG=express:* node ./bin/www
  express:router:route new / +0ms
  express:router:layer new / +1ms
  express:router:route get / +1ms
  express:router:layer new / +0ms
  express:router:route new / +1ms
  express:router:layer new / +0ms
  express:router:route get / +0ms
  express:router:layer new / +0ms
  express:application compile etag weak +1ms
  express:application compile query parser extended +0ms
  express:application compile trust proxy false +0ms
  express:application booting in development mode +1ms
  express:router use / query +0ms
  express:router:layer new / +0ms
  express:router use / expressInit +0ms
  express:router:layer new / +0ms
  express:router use / favicon +1ms
  express:router:layer new / +0ms
  express:router use / logger +0ms
  express:router:layer new / +0ms
  express:router use / jsonParser +0ms
  express:router:layer new / +1ms
  express:router use / urlencodedParser +0ms
  express:router:layer new / +0ms
  express:router use / cookieParser +0ms
  express:router:layer new / +0ms
  express:router use / stylus +90ms
  express:router:layer new / +0ms
  express:router use / serveStatic +0ms
  express:router:layer new / +0ms
  express:router use / router +0ms
  express:router:layer new / +1ms
  express:router use /users router +0ms
  express:router:layer new /users +0ms
  express:router use / <anonymous> +0ms
  express:router:layer new / +0ms
  express:router use / <anonymous> +0ms
  express:router:layer new / +0ms
  express:router use / <anonymous> +0ms
  express:router:layer new / +0ms

当你对这个应用发送请求的时候,你将会看到日志:

express:router dispatching GET / +4h
  express:router query  : / +2ms
  express:router expressInit  : / +0ms
  express:router favicon  : / +0ms
  express:router logger  : / +1ms
  express:router jsonParser  : / +0ms
  express:router urlencodedParser  : / +1ms
  express:router cookieParser  : / +0ms
  express:router stylus  : / +0ms
  express:router serveStatic  : / +2ms
  express:router router  : / +2ms
  express:router dispatching GET / +1ms
  express:view lookup "index.jade" +338ms
  express:view stat "/projects/example/views/index.jade" +0ms
  express:view render "/projects/example/views/index.jade" +1ms

为了只查看由router产生的日志,设置DEBUG变量的值为express:router;同样地,如果只想查看由应用产生的日志,设置DEBUG变量的值为express:application

express产生的应用:

express命令产生的应用也会使用DEBUG这个模块,它的调试命名空间局限于应用的名字。

如果你使用下面的命令创建一个应用:

$ express sample-app

你可以使用以下的命令来激活调试状态:

$ DEBUG=sample-app node ./bin/www

你可以使用逗号将一系列名字分开来使用多个调试命令空间,如下:

$ DEBUG=http,mail,express:* node index.js

想要了解更多关于调试的信息,请阅读调试指南

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值