美文网首页
NodeJs 网络框架 express

NodeJs 网络框架 express

作者: yangweigbh | 来源:发表于2017-02-01 13:19 被阅读173次

安装

npm install express --save

运行

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

生成模板工程

安装express-generator

npm install express-generator -g

生成模板

express --view=jade myapp

安装依赖库

cd myapp && npm install

运行

DEBUG=myapp:* npm start

windows: set DEBUG=myapp:* & npm start

生成文件目录结构

Paste_Image.png

Serving静态文件

app.use(express.static('public'))

http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html

Serve多个文件夹

app.use(express.static('public'))
app.use(express.static('files'))

serve 到不同的路径

app.use('/static', express.static('public'))

http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html

Route

// GET method route
app.get('/', function (req, res) {
  res.send('GET request to the homepage')
})

// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage')
})

支持的HTTP方法:

get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search, and connect.

app.all()对特定路径的所有请求方法都会调用。通常用来实现中间件

app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

path 接受正则表达式

request path 参数

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }

同一路径的request handler可以设置多个

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (req, res) {
  res.send('Hello from B!')
})

也可以通过数组设置

var cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

var cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

var cb2 = function (req, res) {
  res.send('Hello from C!')
}

app.get('/example/c', [cb0, cb1, cb2])

app.route()将同一路径的不同方法的handler做链式定义

app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (req, res) {
    res.send('Update the book')
  })

express.Router定义模块化的router

var express = require('express')
var router = express.Router()

// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', function (req, res) {
  res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
  res.send('About birds')
})

module.exports = router

Middleware

Express本身没有多少功能,主要功能是由各种middleware来实现的

Middleware 由接受req,res和next(可选)参数的函数实现。

Middleware可以:

  • 执行代码
  • 修改req和res
  • 结束req-res cycle
  • 执行下一个middleware

如果一个middleware没有结束req-res cycle,则要调用next来执行下一个middleware

有5种middleware

  • Application-level middleware

app.use() and app.METHOD()设置application-level middleware

  • Router-level middleware

设置在Router上的middleware

var app = express()
var router = express.Router()

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next router
  if (req.params.id === '0') next('route')
  //跳转到下一个matching route function
  else next() // 跳转到同一个Route function的下一个handler
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id)
  res.render('special')
})

// mount the router on the app
app.use('/', router)
  • Error-handling middleware
    函数签名为(err, req, res, next)
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})
  • Built-in middleware

express.static(root, [options])

  • Third-party middleware

通过npm安装,然后在application-level使用

npm install cookie-parser

var cookieParser = require('cookie-parser')

// load the cookie-parsing middleware
app.use(cookieParser())

Error handle

可以定义多个error handler,前一个handler通过调用next(err)来调用下一个error handler

app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)

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

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

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

如果在request handler中调用next时传入非"route"的参数,则会认为产生了错误,会跳过剩下的request handler,调用error handler

如果error handler没有调用next,则要负责生产response,否则request会hang住,无法垃圾回收

Express 有一个默认的error handler,会将错误的堆栈输出到client,production环境下不输出堆栈。

当在最后一个自定义的error handler中调用next(err)时,会委托给默认error handler处理。

相关文章

网友评论

      本文标题:NodeJs 网络框架 express

      本文链接:https://www.haomeiwen.com/subject/fezkittx.html