Express 的使用

以下内容,基于 Express 4.x 版本

Node.js 的 Express

Express 估计是那种你第一次接触,就会喜欢上用它的框架。因为它真的非常简单,直接。

在当前版本上,一共才这么几个文件:

lib/
├── application.js
├── express.js
├── middleware
│   ├── init.js
│   └── query.js
├── request.js
├── response.js
├── router
│   ├── index.js
│   ├── layer.js
│   └── route.js
├── utils.js
└── view.js

这种程度,说它是一个“框架”可能都有些过了,几乎都是工具性质的实现,只限于 Web 层。

当然,直接了当地实现了 Web 层的基本功能,是得益于 Node.js 本身的 API 中,就提供了 net 和 http 这两层, Express 对 http 的方法包装一下即可。

不过,本身功能简单的东西,在 package.json 中却有好长一串 dependencies 列表。

Hello World

在跑 Express 前,你可能需要初始化一个 npm 项目,然后再使用 npm 安装 Express

mkdir p
cd p
npm init
npm install express --save

新建一个 app.js :

const express = require('express');
const app = express();
app.all('/', (req, res) => res.send('hello') );
app.listen(8888);

调试信息是通过环境变量 DEBUG 控制的:

const process = require('process');
process.env['DEBUG'] = 'express:*';

这样就可以在终端看到带颜色的输出了,嗯,是的,带颜色控制字符,vim 中直接跑就 SB 了。

应用 Application

Application 是一个上层统筹的概念,整合“请求-响应”流程。 express() 的调用会返回一个 application ,一个项目中,有多个 app 是没问题的:

const express = require('express');

const app = express();
app.all('/', (req, res) => res.send('hello'));
app.listen(8888);

const app2 = express();
app2.all('/', (req, res) => res.send('hello2'));
app2.listen(8889);

多个 app 的另一个用法,是直接把某个 path 映射到整个 app :

const express = require('express');

const app = express();

app.all('/', (req, res) => {
    res.send('ok');
});

const app2 = express();
app2.get('/xx', (req, res, next) => res.send('in app2') )
app.use('/2', app2)

app.listen(8888);

这样,当访问 /2/xx 时,就会看到 in app2 的响应。

前面说了 app 实际上是一个上层调度的角色,在看后面的内容之前,先说一下 Express 的特点,整体上来说,它的结构基本上是“回调函数串行”,无论是 app ,或者 route, handle, middleware这些不同的概念,它们的形式,基本是一致的,就是 (res, req, next) => {} ,串行的流程依赖 next() 的显式调用。

我们把 app 的功能,分成五个部分来说。

路由 - Handler 映射

app.all('/', (req, res, next) => {});
app.get('/', (req, res, next) => {});
app.post('/', (req, res, next) => {});
app.put('/', (req, res, next) => {});
app.delete('/', (req, res, next) => {});

上面的代码就是基本的几个方法,路由的匹配是串行的,可以通过 next() 控制:

const express = require('express');

const app = express();

app.all('/', (req, res, next) => {
    res.send('1 ');
    console.log('here');
    next();
});

app.get('/', (req, res, next) => {
    res.send('2 ');
    console.log('get');
    next();
});

app.listen(8888);

对于上面的代码,因为重复调用 send() 会报错。

同样的功能,也可以使用 app.route() 来实现:

const express = require('express');

const app = express();

app.route('/').all( (req, res, next) => {
    console.log('all');
    next();
}).get( (req, res, next) => {
    res.send('get');
    next();
}).all( (req, res, next) => {
    console.log('tail');
    next();
});

app.listen(8888);

app.route() 也是一种抽象通用逻辑的形式。

还有一个方法是 app.params ,它把“命名参数”的处理单独拆出来了(我个人不理解这玩意儿有什么用):

const express = require('express');

const app = express();

app.route('/:id').all( (req, res, next) => {
    console.log('all');
    next();
}).get( (req, res, next) => {
    res.send('get');
    next()
}).all( (req, res, next) => {
    console.log('tail');
});

app.route('/').all( (req, res) => {res.send('ok')});

app.param('id', (req, res, next, value) => {
    console.log('param', value);
    next();
});

app.listen(8888);

app.params 中的对应函数会先行执行,并且,记得显式调用 next() 。

Middleware

其实前面讲了一些方法,要实现 Middleware 功能,只需要 app.all(/.*/, () => {}) 就可以了, Express 还专门提供了 app.use() 做通用逻辑的定义:

const express = require('express');

const app = express();

app.all(/.*/, (req, res, next) => {
    console.log('reg');
    next();
});

app.all('/', (req, res, next) => {
    console.log('pre');
    next();
});

app.use((req, res, next) => {
    console.log('use');
    next();
});

app.all('/', (req, res, next) => {
    console.log('all');
    res.send('/ here');
    next();
});

app.use((req, res, next) => {
    console.log('use2');
    next();
});

app.listen(8888);

注意 next() 的显式调用,同时,注意定义的顺序, use() 和 all() 顺序上是平等的。

Middleware 本身也是 (req, res, next) => {} 这种形式,自然也可以和 app 有对等的机制——接受路由过滤, Express 提供了 Router ,可以单独定义一组逻辑,然后这组逻辑可以跟 Middleware一样使用。

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

app.all('/', (req, res) => {
    res.send({a: '123'});
});

router.all('/a', (req, res) => {
    res.send('hello');
});

app.use('/route&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值