媒介
运用node直接完成服务器是运用http模块,Express和Koa都是在其上做的封装,
这篇wiki只是想直观的看看封装前后基础运用上的差别,先不去斟酌深切的东西。
一、http模块
1.1 处置惩罚get要求
var http = require("http");
http.createServer(function(req, res) {
// 主页
if (req.url == "/") {
res.writeHead(200, { "Content-Type": "text/html" });
res.write("Welcome to the homepage!");
res.end("Welcome to the homepage!");
}
// About页面
else if (req.url == "/about") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end("Welcome to the about page!");
}
// 404毛病
else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("404 error! File not found.");
}
}).listen(8080, "localhost");
http模块的createServer直接就可以建立一个服务器的实例,然后挪用实例的listen要领,传入监听的端口与主机就ok了,
处置惩罚函数把http的request和response对象作为两个参数举行操纵。
完成路由: 经由过程要求的url来推断
写相应头部:res.writeHead要领
写相应body: res.write
完毕相应: res.end
1.2 处置惩罚Post要求
var http = require('http');
http.createServer(function (req, res) {
var content = "";
req.on('data', function (chunk) {
content += chunk;
});
req.on('end', function () {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("You've sent: " + content);
res.end();
});
}).listen(8080);
监听req的data和end事宜,data事宜会在数据吸收过程当中,每收到一段数据就触发一次,
吸收到的数据被传入回调函数。end事宜则是在一切数据吸收完成后触发。
二、Express框架
2.1 中间件
简单说,中间件(middleware)就是处置惩罚HTTP要求的函数。它最大的特征就是,一个中间件处置惩罚完,再通报给下一个中间件。
App实例在运转过程当中,会挪用一系列的中间件。每一个中间件可以从App实例,吸收三个参数,
依次为request对象(代表HTTP要求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。
每一个中间件都可以对HTTP要求(request对象)举行加工,而且决议是不是挪用next要领,将request对象再传给下一个中间件。
一个不举行任何操纵、只通报request对象的中间件,就是下面如许。
function uselessMiddleware(req, res, next) {
next();
}
上面代码的next就是下一个中间件。假如它带有参数,则代表抛出一个毛病,参数为毛病文本。
function uselessMiddleware(req, res, next) {
next('出错了!');
}
抛出毛病今后,背面的中间件将不再实行,直到发明一个毛病处置惩罚函数为止。
use是express注册中间件的要领。
app.use(function(request, response, next) {
console.log("In comes a " + request.method + " to " + request.url);
next();
});
app.use(function(request, response) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Hello world!\n");
});
2.2 路由的完成
2.2.1 request.url
可以运用request.url属性,推断要求的网址,从而返回差别的内容,完成路由。
app.use(function(request, response, next) {
if (request.url == "/") {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the homepage!\n");
} else {
next();
}
});
app.use(function(request, response, next) {
if (request.url == "/about") {
response.writeHead(200, { "Content-Type": "text/plain" });
} else {
next();
}
});
2.2.2 use等要领
除了在回调函数内部推断要求的网址,use要领也许可将要求网址写在第一个参数。
这代表,只要要求途径婚配这个参数,背面的中间件才会见效。无疑,如许写越发清楚和轻易。
app.use("/home", function(request, response, next) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the homepage!\n");
});
针对差别的要求,use可以有差别的别号,离别对应http的要领,包含get post put post delete。
2.2.3 运用Express.Router
var router = express.Router();
router.get('/', function(req, res) {
res.send('首页');
});
router.get('/about', function(req, res) {
res.send('关于');
});
app.use('/', router);
router可以自在挂载和直接把路由写在use上比拟,可以为递次誊写带来更大的灵活性。
2.3 处置惩罚POST要求
为何要零丁说这个post要求,由于猎取request的body不是可以经由过程request的一个body属性就可以够的,
经由过程http处置惩罚post的要求中我们可以看到,须要经由过程监听request的data和end要领举行拼接,由于body能够分屡次传过来。
运用框架的优点就是有人写了中间件,可以直接用。Express中处置惩罚body的中间件用body-parser
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
body-parser供应了一下几种转换花样
JSON body parser
Raw body parser
Text body parser
URL-encoded form body parser
运用中间件今后,可以直接运用request.body直接猎取转换后的body。
router.post('/testpost', function(req, res, next) {
console.log('testpost');
res.send(req.body);
});
三、Koa框架
一个Koa运用就是一个对象,包含了一个middleware数组,这个数组由一组Generator函数构成。
这些函数担任对HTTP要求举行种种加工,比方天生缓存、指定代办、要求重定向等等。
var koa = require('koa');
var app = koa();
app.use(function *(){
this.body = 'Hello World';
});
app.listen(3000);
可以看到,Koa框架和Express框架运用起来很类似。那末重点说的应该是Koa框架的差别之处:
1.中间件用Generator函数,所以中间件运用了Generator函数的中缀守候特征
2.把request和response对象封装到了context中,经由过程this接见,所以操纵的api会有差别。
3.1 中间件
Koa中间件与Express的差别就在于它是Generator函数,Generator函数内部运用yield敕令,将递次的实行权转交给下一个中间件,
即yield next,要比及下一个中间件返回效果,才会继承往下实行,所以是嵌套实行的递次。
app.use(function *(next){
console.log('>> one');
yield next;
console.log('<< one');
});
app.use(function *(next){
console.log('>> two');
this.body = 'two';
console.log('<< two');
});
输出:
>> one
>> two
<< one
<< two
所以当须要有异步操纵的时刻,我们可以用yield,将控制权交给它,不势必处置惩罚逻辑写在回调函数中。
Generator函数会返回一个遍历器对象,yield语句就是停息的标识,Koa框架则会自动的遍历Generator函数,直到完毕,返回http要求。
所以在什么时候返回http要求,koa没有像http模块和Express框架那样显现的指定,比方挪用res.end,res.send等要领来完毕http相应。
koa则是在实行完一切中间件今后自动的返回http要求。不会守候未完成的异步操纵
3.2路由
两种体式格局
一种是用this.path做推断
let koa = require('koa')
let app = koa()
// normal route
app.use(function* (next) {
if (this.path !== '/') {
return yield next
}
this.body = 'hello world'
});
一种是用koa-router插件,类似于Express的use和一系列http动词要领。
var app = require('koa')();
var Router = require('koa-router');
var myRouter = new Router();
myRouter.get('/', function *(next) {
this.response.body = 'Hello World!';
});
app.use(myRouter.routes());
app.listen(3000);
3.3 context对象
中间件当中的this示意上下文对象context,代表一次HTTP要乞降回应,即一次接见/回应的一切信息,都可以从上下文对象取得。
context对象封装了request和response对象,而且供应了一些辅佐要领。每次HTTP要求,就会建立一个新的context对象。
context对象的全局属性。
request:指向Request对象
response:指向Response对象
req:指向Node的request对象
req:指向Node的response对象
app:指向App对象
state:用于在中间件通报信息。
3.4 处置惩罚Post的要求
实在就是怎样猎取reauest中的body,运用中间件co-body,处置惩罚后可以经由过程this.request.body接见
// application/json
var body = yield parse.json(this);
// application/x-www-form-urlencoded
var body = yield parse.form(this);
// text/plain
var body = yield parse.text(this);