前言

利用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);

浅谈Http模块,Express和Koa实现http服务相关推荐

  1. sap 双计量单位_[原创]浅谈MM模块的双计量单位(二)

    [原创]浅谈MM模块的双计量单位(二) 本博文为隐身人原创作品,请勿转载. 我们继续按照以下的步骤来执行双计量单位的有关流程. 第一步:切换到批次类的"特性"视图,将我们刚才创建的 ...

  2. 浅谈node结合express第三方插件使用跨域

    目录 node实现跨域 CORS实现跨域 jsonp 创建一个服务器 index.js文件的 路由的配置! user.js文件 => 定义着user的相关路由 前端发起一个jsonp请求 服务器 ...

  3. 浅谈 OneAPM 在 express 项目中的实践

    [编者按]OneAPM 运营团队,近日在 github 上发现了一篇文章,特别奉献给大家.本文作者王宇先生从2015年年初就开始使用我们的产品,也是OneAPM 的忠实用户. OneAPM 是一个优秀 ...

  4. 小白扫盲:浅谈web应用在nat123下的vip服务

    nat123是一个IP穿透及域名代理服务,使用它,可以在任何网络下可上网即可搭建自己的服务器,并提供外网服务. nat123可以应用的范围很广,可以适配网站.远程桌面.数据库.SSH访问.办公OA.管 ...

  5. 路面监控服务器怎么维修,浅谈道路视频监控系统的维护保养服务

    众所周知,道路视频监控系统通常都纳入到平安城市这个大的建设概念中来,平安城市的广义内容包含了110.119和112这些统一的服务平台.但具体到安防行业,平安城市主要针对的是闭路监控电视系统. 国内的平 ...

  6. 三英战豪强,思绪走四方。浅谈我眼中的express、koa和koa2

    支持原创,本文为转载文章,转载是为了备忘或丢失,这么好的文章. https://www.jianshu.com/p/3806417a1991?from=timeline 前言 跟好朋友打赌,我要来个技 ...

  7. python sys模块作用_浅谈Python中的模块

    模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Mod ...

  8. 浅谈STM32的DMA模块的使用

    浅谈STM32的DMA模块的使用 转自:http://blog.ednchina.com/jack_chang/123085/message.aspx http://article.ednchina. ...

  9. ant man 什么意思_浅谈为什么很多蓝牙模块厂家选择nRF52832?

    浅谈为什么很多蓝牙模块厂家选择nRF52832? 现在蓝牙低功耗(BLE)SOC作为新一代蓝牙,以其低功耗的优势,正凸显出强大的市场竞争力,而其中Nordic公司的nRF52832这一款低功耗蓝牙芯片 ...

最新文章

  1. Matlab中寻找二值图像最大联通域的算法
  2. 取得COM对象的UUID并以string输出
  3. 一个合格网络管理员的成长经历
  4. 最全 | Redis可视化工具横向评测
  5. SequoiaDB 巨杉数据库
  6. Windows mysql boost_Win7下Boost库的安装
  7. 基于数据空间的电子病历数据融合与应用平台
  8. 使用token实现在有效期内APP自动登录功能
  9. 【三层】无法直接启动带有“类库输出类型”的项目
  10. linux服务端修改EDT为东八区,EDT开发环境配置
  11. vue第一天 认识vue与vue基本使用
  12. 拓端tecdat|R语言关联挖掘实例(购物篮分析)
  13. en开头的单词_大道至简:为什么记英语单词要先了解从拉丁语到法语的读音变化...
  14. 冯乐乐之二 shader的数学
  15. windows使用命令行修改用户密码
  16. 借贷记账法--借贷记账法 (Debit and Credit)
  17. 什么?!NEON还要优化?
  18. html表格突出显示,java-如何突出显示jtable单元格的文本?
  19. target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target S
  20. poi 设置单元格背景色

热门文章

  1. 在EditText前面添加一个搜索的小图片
  2. oracle 的服务器进程(PMON, SMON,CKPT,DBWn,LGWR,ARCn)
  3. 在Simulink中创建库
  4. 周立功-成功心法(2):通过讲故事营销自己
  5. ArrayList使用方法
  6. 程序怎么才能把自己的删除掉?
  7. 程序架构探讨—007 应用服务器集群的伸缩性之链路负载均衡
  8. “智慧城市”方便百姓生活服务企业发展
  9. mongodb常用管理命令
  10. delphi xe2学习笔记(1)