Express 学习笔记

数据库挂了。谷歌快照恢复补档。首发时间2017-4-8

以下原文:

前一阵子一直比较忙(绝对不是忙着打昆特牌),所以今天有空就来除一波草。记录一下之前学的东西。当然。基本都是个人理解。有错误的话还是请指正。


首先。我们得知道 Express 到底是个什么东西,它在整个请求中扮演了什么角色。
我们知道 Node.js 可以监听服务器上的一个端口,所有发向该端口的请求都可以被 Node 获取。而针对不同的请求我们需要提供不同的处理函数。
Express 就在这里提供了一个解决方案可以让你快速的路由请求。
首先,我们使用

即可便捷的安装 Express。
然后我们在文件中使用

来引入 express 包
在 Express 中使用 listen 方法可以便捷的监听端口。

这时 Express 就会监听 12450 端口,所有发往该端口的请求都会被 Express 接收。
在 Express 中使用以下方法可以建立路由对处理函数的对应关系。

这可以将一个发往 yoursite/your/path 的请求转交给 handleFunction 处理
handleFunction 的参数要求为 request, response, next。 request 是请求的对象,response 是应答对象, next 则是回调函数。举例来说

此时发往 /your/path 的请求就会在控制台输出 0 1 done.
我们可以把 Express 看作一个筛子,每一个 handleFunction 都可以对请求进行处理。
Express 总是会按顺序执行每一个路由连接,并且如果上一个处理函数没有调用 next 的话。下一个处理函数就不会执行。
这样,我们就可以方便的进行身份验证、打印日志以及预处理。让我们可以更专注于编写请求处理的逻辑。
但是有一个问题。我们将所有的请求放在 ‘/api’ 路径下,我们每次使用时都需要写全 ‘/api/xxx’ 这样很麻烦。
短一点还好,如果路径很长或者路径嵌套了很多层的话看起来会很乱,而且这也不利于路由管理的模块化。
Express 为此提供了 Router 对象。
Express 规定了 express.Router 也是一个带有 request, response, next 参数的方法,所以我们可以将一个 router 对象作为某个请求路径的处理函数。
举例来说

这时我们就不需要在每个路由语句中都带上长长的参数了。以上的写法等同于

明显可以看出使用 Router 的路径更加清晰易读。
这时我们还有一个问题。如果我们想要监听指定的请求类型怎么办?
很简单,将 use 换成你想监听的请求类型即可。例如

这样即可针对不同的请求类型执行不同的处理函数了。
以上介绍了处理函数,接下来介绍静态文件的处理。
如果使用 Nginx 反向代理的话最好是把静态文件交给 Nginx 来处理。但有时因为种种原因或者只是出于操作简单之类的考虑,我们会使用 Express 来路由。
方法很简单。把你所有的静态文件整理好,放在一个路径下,然后使用如下语句将该路径绑定到某个请求 url 上即可。

这时假设你要读取一张图片 testImg.jpg ,访问 /static/testImg.jpg 即可。
这里请尽量不要使用 ./your_path 因为这样有时会读不到文件夹。
这里有一个小坑就是 Express 提供了一个 response.type 方法来设定 response 的 Content-type。
例如 res.type(‘html’) 或者 res.type(‘json’) 之类,有时会和你自定的 Content-type 冲突,所以尽量使用 res.type() 方法来定义 Content-type。具体的对应关系如下:

 


4.21更新

遇到了一个坑。

Express 中的 router.use 方法有一种批量添加路由的方式。例如:

这样的本意是将 /hello 和 / 路径全部绑定到处理函数上。
但是由于 Express 永远是顺序执行绑定的处理函数,即使在批量路由时也会按数组元素顺序依次绑定。
有了这个保障,所以 Express 本身的路径匹配机制就是很宽泛的匹配。
即 / 也可以匹配到发往 /hello 的请求。这时又由于 Express 的筛子特性就会导致 /hello 永远不会被匹配。
这在直接绑定处理函数时是没有任何问题的。因为处理函数只专注于本身的逻辑,路径的判断已经交给了 Express 处理。
但是有一个情况比较特殊,就是使用 Router 对象作为处理函数的情况。
这时上例中的写法就会对 Router 对象造成困扰。
例如你希望处理 /hello/world 的请求时,你希望请求被 /hello 响应,所以你在 Router 对象中填入路径 /world 并绑定处理函数。
但实际上他只能响应到 /world 请求,因为请求被 / 给拦截了。

不过 router.METHOD 的几种方法是没有这个限制的,会做到精确匹配。


4月25更新。

use 方法和 post, get, put, delete 等方法不同,use 方法第一个参数不填默认为 ‘/’ ,而其他的 method 方法是没有默认路径的说法的,不填那么就什么都不会匹配。

发表评论

电子邮件地址不会被公开。