前言
-
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
这也就让我们可以脱离浏览器运行JavaScript代码。 -
在Node.js渐渐成熟走向商业化应用的过程中,必须要提起Express,Koa框架,它们均来自同一作者TJ--node圈中的人物,诞生于Nodejs发展的不同时期,在Ecmascript语言规范的发展中前行。
在Express诞生前,没有成熟轮子,需要通过Nodejs基础模块构建应用
const http = require("http");
http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello world");
response.end();
}).listen(8081);
Express
基于 Node.js 平台,快速、开放、极简的 Web 开发框架,这来自Express官方描述。
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(3001, () => {
console.info(`Server has started, 地址为: http://0.0.0.0:3001`)
})
Express是一个自身功能极简,完全是路由和中间件构成一个web开发框架:从本质上来说,一个Express应用就是在调用各种中间件。
可以看出中间件在Express开发中的重要性,这里主要就介绍一下中间件。
image.png1、内置中间件
express.static 是Express目前唯一内置的一个中间件。用来处理静态资源文件。
例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了:
app.use(express.static('public'))
现在,你就可以访问 public 目录中的所有文件了:
http://localhost:3001/images/kitten.jpg
http://localhost:3001/css/style.css
http://localhost:3001/js/app.js
http://localhost:3001/images/bg.png
http://localhost:3001/hello.html
2、自定义中间件
这是一个名为“myLogger”的中间件函数的简单示例。当对应用程序的请求通过时,此函数只打印“LOGGED”。中间件函数被分配给名为的变量myLogger。
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
每次应用程序收到请求时,它都会向终端输出消息“LOGGED”。
中间件加载的顺序很重要:首先加载的中间件函数也会先执行。
如果myLogger在到根路径的路由之后加载,则请求永远不会到达它并且应用程序不会打印“LOGGED”,因为根路径的路由处理程序终止请求 - 响应循环。
中间件函数myLogger只是打印一条消息,然后通过调用该next()函数将请求传递给堆栈中的下一个中间件函数。
Koa
Koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。使用 Koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。Koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。
// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');
// 创建一个Koa对象表示web app本身:
const app = new Koa();
// 对于任何请求,app将调用该异步函数处理请求:
// 参数ctx是由koa传入的封装了request和response的变量,我们可以通过它访问request和response,next是koa传入的将要处理的下一个异步函数。
// 这里首先用await next();处理下一个异步函数,然后,设置的返回内容。
app.use(async (ctx, next) => {
await next();
ctx.body = 'Hello World';
});
// 在端口3001监听:
app.listen(3001);
console.info(`Server has started, 地址为: http://0.0.0.0:3001`)
Koa middleware
首先我们看一下执行的核心代码
app.use(async (ctx, next) => {
await next();
ctx.body = 'Hello World';
});
每收到一个http请求,Koa就会调用通过app.use()注册的async函数,并传入ctx和next参数。
我们可以对ctx操作,并设置返回内容。但是为什么要调用await next()?
因为Koa 中间件以更传统的方式级联,使用 async 功能,我们可以实现 “真实” 的中间件。通过一系列功能直接传递控制,直到一个返回,Koa 调用“下游”,然后控制流回“上游”。
下面以 “Hello World” 的响应作为示例,当请求开始时首先请求流通过 x-response-time 和 logging 中间件,然后继续移交控制给 response 中间件。当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件。当在下游没有更多的中间件执行后,堆栈将展开并且每个中间件恢复执行其上游行为。
const Koa = require('koa');
const app = new Koa();
// logger
app.use(async (ctx, next) => {
await next(); // 调用下一个middleware
const rt = ctx.response.get('X-Response-Time');
console.log(`${ctx.method} ${ctx.url} - ${rt}`); // 打印日志
});
// x-response-time
app.use(async (ctx, next) => {
const start = Date.now(); // 当前时间
await next(); // 调用下一个middleware
const ms = Date.now() - start; // 耗时时间
ctx.set('X-Response-Time', `${ms}ms`); // 打印耗时时间
});
// response
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3001);
middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。
此外,如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。这种情况也很常见,例如,一个检测用户权限的middleware可以决定是否继续处理请求,还是直接返回403错误:
app.use(async (ctx, next) => {
if (await checkUserPermission(ctx)) {
await next();
} else {
ctx.response.status = 403;
}
});
总结
- koa是一个比express更精简,使用node新特性的中间件框架,相比之前express就是一个庞大的框架。
Express基于ES5语法,通过回调组合逻辑。在复杂逻辑中会包含大量回调嵌套,难以捕捉问题,不便调试。当下Es6,Es7盛行,可以通过相关三方库完善支持Promise或Async/Await来弥补。
如果你喜欢diy,可以考虑koa,它有足够的扩展和中间件,而且自己写很简单
如果你想简单点,找一个框架啥都有,那么先使用express
- 中间件理解
浏览器向服务器发送一个请求后,服务器直接通过request.定位属性的方式得到通过request携带过去的数据(有用户输入的数据和浏览器本身的数据信息)。这中间就一定有一个函数将这些数据分类做了处理,已经处理好了,最后让request对象调用使用。对的,这个处理数据处理函数就是我们要说的 中间件 。
- 中间件可以总结为以下两点:
1、封装了一些处理一个完整事件的功能函数。
2、封装了一些或许复杂但肯定是通用的功能。
参考:
网友评论