阅读 126

node.js框架太多?从Express开始吧

Express 可以说是最经典的 node.js Web 框架,其地位就好比 Tomcat、Jetty 之于 Java Web Server 的地位,本文一次总结所有 Express 的常用API。话不多说,让我们开始吧!

Express 的编程模型

启动 --> fn1 --> fn2 --> fn3 --> ... --> 结束

这里面的每个 fn 就是中间件(middleware)

中间件的通用写法如下:

const fn = (request, response, next) => {
    // process current logic
    ...
    next() // pass control to the next handler
} // 为了方便起见,以下所有的fn或中间件的写法都是这里的fn

app.use(fn)
复制代码

express() 相关 API

express.json()

用于解析 JSON 格式的请求,用法:

app.use(express.json())
app.use((request, response, next) => {
    const jsonObj = request.body // 可以直接得到JSON数据转成的JS对象
})
复制代码

express.static()

用于在提供的目录搭建一个静态服务器,如果请求的文件在这个目录中,就加载,如果不在,就跳过这行代码。用法是:

app.use(express.static('static')) // 为static目录开启一个静态服务器
复制代码

express.Router()

创建一个迷你 application,可以像app.use()app.get()app.post()一样使用,具体可以参见下方 app 的使用方法。用法:

const express = require('express');
const router = express.Router();

router.get('/', function(req, res, next) {
  ...
});

module.exports = router;
复制代码

app 相关 API

app.use()

最常用的API,挂载一个中间件到指定位置,用法:

app.use('/users', fn);
复制代码

app.get()

第二常用的API,使用指定的回调函数将 HTTP GET 请求路由到指定的路径。用法:

app.get('/getName', fn);
复制代码

app.post()

并列第二常用的API,使用指定的回调函数将 HTTP POST 请求路由到指定的路径。用法:

app.post('/getName', fn);
复制代码

request 相关 API

req.body

用于获取 HTTP 请求的请求体,用法:

const express = require('express')

const app = express()

app.use(express.json()) // 解析 application/json 格式的请求
app.use(express.urlencoded({ extended: true })) // 解析 application/x-www-form-urlencoded 格式的请求

app.post('/profile', function (req, res, next) {
  console.log(req.body)
})
复制代码

req.query

获取 HTTP 请求中的查询参数,类型为一个对象,其中包含路由中每个查询字符串参数的属性

// GET /search?q=tobi+ferret
console.dir(req.query.q)
// => 'tobi ferret'

// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
console.dir(req.query.shoe.type)
// => 'converse'

// GET /shoes?color[]=blue&color[]=black&color[]=red
console.dir(req.query.color)
// => ['blue', 'black', 'red']
复制代码

req.path

获取请求 URL 中的请求路径,通常是 xxx.com 后面 / 开头,? 之前的部分,用法:

// example.com/users?sort=desc
console.dir(req.path)
// => '/users'
复制代码

response 相关 API

res.send()

发送一个 HTTP 响应,响应体可以是一个 Buffer 对象,一个字符串,一个对象,或者一个数组,用法:

res.send(Buffer.from('whoop'))
res.send({ some: 'json' })
res.send('<p>some html</p>')
res.status(404).send('Sorry, we cannot find that!')
res.status(500).send({ error: 'something blew up' })
复制代码

res.set()

指定 HTTP 响应头中的特定字段,用法:

res.set('Content-Type', 'text/plain')

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345'
})
复制代码

res.json()

发送一个 JSON 格式的响应,基本用法:

res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })
复制代码

router 示例

先用一段示例代码讲一下参数的概念,

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

router.param

构造一个参数触发器,当参数名为指定参数名时,触发回调,并且只会触发一次,用法:

router.param('id', function (req, res, next, id) {
  console.log('CALLED ONLY ONCE');
  next();
});

router.get('/user/:id', function (req, res, next) {
  console.log('although this matches');
  next();
});
复制代码

router.route()

返回单个路由实例,接下来可以用各种中间件处理 HTTP 请求,用法:

const router = express.Router();

router.param('user_id', function(req, res, next, id) {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id: id,
    name: 'TJ'
  };
  next();
});

router.route('/users/:user_id')
.all(function(req, res, next) {
  // runs for all HTTP verbs first
  // think of it as route specific middleware!
  next();
})
.get(function(req, res, next) {
  res.json(req.user);
})
.put(function(req, res, next) {
  // just an example of maybe updating the user
  req.user.name = req.params.name;
  // save user ... etc
  res.json(req.user);
})
.post(function(req, res, next) {
  next(new Error('not implemented'));
})
.delete(function(req, res, next) {
  next(new Error('not implemented'));
});
复制代码