如何评价 Node.js 的koa框架教程

Node.js框架之express与koa对比分析
提到Node.js开发,不得不提目前炙手可热的2大框架express和koa。Express诞生已有时日,是一个简洁而灵活的web开发框架,使用简单而功能强大。Koa相对更为年轻,是Express框架原班人马基于ES6新特性重新开发的敏捷开发框架,现在可谓风头正劲,大有赶超Express之势。
提到Node.js开发,不得不提目前炙手可热的2大框架express和koa。Express诞生已有时日,是一个简洁而灵活的web开发框架,使用简单而功能强大。Koa相对更为年轻,是Express框架原班人马基于ES6新特性重新开发的敏捷开发框架,现在可谓风头正劲,大有赶超Express之势。
Express和koa都是服务端的开发框架,服务端开发的重点是对HTTP Request和HTTP Response两个对象的封装和处理,应用的生命周期维护以及视图的处理等。 以下将主要通过这些方面,对两者进行一个对比介绍,看看到底有什么区别。
Express主要基于Connect中间件框架,功能丰富,随取随用,并且框架自身封装了大量便利的功能,比如路由、视图处理等等。而koa主要基于co中间件框架,框架自身并没集成太多功能,大部分功能需要用户自行require中间件去解决,但是由于其基于ES6 generator特性的中间件机制,解决了长期诟病的“callback hell”和麻烦的错误处理的问题,大受开发者欢迎。
Express和koa初印象
先来一个Hello World,各自认识一下吧
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
app.listen(3000);
var koa = require('koa');
var route = require('koa-route');
var app = koa();
app.use(route.get('/', function *(){
this.body = 'Hello World';
app.listen(3000);
可以看出来,两者创建一个基础的Web服务都非常简单,可以说几行代码就解决了问题。两者的写法也基本相同,最大的区别是路由处理Express是自身集成的,而koa需要引入中间件。以下是Koa官方文档对于两者特性的一个对比:
重要功能对比介绍
Middleware Kernel
Templating
Sending Files
通过后续的比较,大家其实可以看出,虽然koa看上去比express少集成了很多功能,但是使用起来其实基本一致,因为中间件非常丰富全面,需要什么require进来就行了(不一定要像express那样先帮你require好),使用起来反而更加灵活。
应用生命周期和上下文
我们在项目过程中,经常需要用到在整个应用生命周期中共享的配置和数据对象,比如服务URL、是否启用某个功能特性、接口配置、当前登录用户数据等等。属于比较基础的功能,两者都非常方便,koa的application context感觉使用起来更方便一点。
app.set('enableCache', true)
app.get('enableCache')
app.disable('cache')
app.disabled('cache')
app.enable('cache')
app.enabled('cache')
app.locals.user = {name:"Samoay", id:1234};
app.enableCache = true;
app.use(function *(next){
console.log(this.app.enableCache);
this.app.enableCache = false;
this.staticPath = 'static';
this.state.user = {name:"Samoay", id:1234};
请求 HTTP Request
服务器端需要进行什么处理,怎么处理以及处理的参数都依赖客户端发送的请求,两个框架都封装了HTTP Request对象,便于对这一部分进行处理。以下主要举例说明下对请求参数的处理,其它例如头信息、Cookie等请参考官方文档。两者除了写法上稍有区别,没太大区别。GET参数都可以直接通过Request对象获取,POST参数都需要引入中间件先parse,再取值。
req.query.order
req.query.shoe.color
app.get('/user/:id?', function userIdHandler(req, res) {
console.log(req.params.id);
res.send('GET');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/', function (req, res) {
console.log(req.body);
res.json(req.body);
this.request.query
var route = require('koa-route');
app.use(route.get('/post/:id', function *(id){
console.log(id);
var parse = require('co-body');
app.use(route.post('/post/new', function *(){
var post = yield parse(this.request);
console.log(post);
路由 Route
收到客户端的请求,服务需要通过识别请求的方法(HTTP Method: GET, POST, PUT...)和请求的具体路径(path)来进行不同的处理。这部分功能就是路由(Route)需要做的事情,说白了就是请求的分发,分发到不同的回调方法去处理。
app.all('*', authentication, loadUser);
app.all('*', requireAuthentication)
app.all('*', loadUser);
app.all('/api/*', requireAuthentication);
app.get('/user/:id', function(req, res) {
res.send('user ' + req.params.id);
app.post('/user/create', function(req, res) {
res.send('create new user');
这里需要说明2个问题,首先是app.get,在应用生命周期中也有一个app.get方法,用于获取项目配置。Express内部就是公用的一个方法,如果传入的只有1个参数就获取配置,2个参数就作为路由处理。其次是app.use('*', cb) 与app.all('*', cb) 的区别,前者是中间件方式,调用是有顺序的,不一定会执行到;后者是路由方式,肯定会执行到。
var route = require('koa-route');
app.use(route.get('/', list));
app.use(route.get('/post/new', add));
app.use(route.get('/post/:id', show));
app.use(route.post('/post', create));
var router = require('koa-router')();
router.get('/', list)
.get('/post/new', add)
.get('/post/:id', show)
.post('/post', create);
app.use(router.routes())
.use(router.allowedMethods());
视图 Views
Express框架自身集成了视图功能,提供了consolidate.js功能,可以是有几乎所有Javascript模板引擎,并提供了视图设置的便利方法。Koa需要引入co-views中间件,co-views也是基于consolidate.js,支持能力一样强大。
app.set('views', __dirname + '/tpls')
app.set('view engine', 'html')
app.engine(ext, callback)
app.engine('html', require('ejs').renderFile)
var engines = require('consolidate')
app.engine('html', engines.handlebars)
app.engine('tpl', engines.underscore)
app.get('list', function(res, req){
res.render('list', {data})
var views = require('co-views')
var render = views('tpls', {
map: { html: 'swig' },
default: "jade"
var userInfo = {
name: 'tobi',
species: 'ferret'
html = render('user', { user: userInfo })
html = render('user.jade', { user: userInfo })
html = render('user.ejs', { user: userInfo })
返回 HTTP Response
获取完请求参数、处理好了具体的请求、视图也准备就绪,下面就该返回给客户端了,那就是HTTP Response对象了。这部分也属于框架的基础部分,各种都做了封装实现,显著的区别是koa直接将输出绑定到了ctx.body属性上,另外输出JSON或JSONP需要引入中间件。
res.render('tplName', {data})
res.jsonp({ user: 'Samoay' })
res.jsonp({ user: 'Samoay' })
res.send(new Buffer('whoop'))
res.send({ some: 'json' })
res.send('&p&some html&/p&')
res.status(200)
app.use(route.get('/post/update/:id', function *(id){
this.status = 404;
this.body = 'Page Not Found';
var views = require('co-views');
var render = views('tpls', {
default: "jade"
app.use(route.get('/post/:id', function *(id){
var post = getPost(id);
this.status = 200;
this.body = yield render('user', post);
var json = require('koa-json');
app.use(route.get('/post/:id', function *(id){
this.body = {id:1234, title:"Test post", content:"..."};
中间件 Middleware
对比了主要的几个框架功能方面的使用,其实区别最大,使用方式最不同的地方是在中间件的处理上。Express由于是在ES6特性之前的,中间件的基础原理还是callback方式的;而koa得益于generator特性和co框架(co会把所有generator的返回封装成为Promise对象),使得中间件的编写更加优雅。
var x = function (req, res, next) {
return next()
return next(err)
return res.send('show page')
app.use(function *(){
该文章来自于阿里巴巴技术协会(ATA)
作者:金鸿
版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
用云栖社区APP,舒服~
【云栖快讯】浅析混合云和跨地域网络构建实践,分享高性能负载均衡设计,9月21日阿里云专家和你说说网络那些事儿,足不出户看直播,赶紧预约吧!&&
重要功能对比介绍 怎么什么也没有?
改用koa-router
基于全网公开发布数据、传播路径和受众群体画像,利用语义分析、情感算法和机器学习,分析公众对品牌形象、热点事件和公...
阿里云推出的一款移动App数据统计分析产品,为开发者提供一站式数据化运营服务
阿里巴巴自主研发的海量数据实时高并发在线分析云计算服务,使得您可以在毫秒级针对千亿级数据进行即时的多维分析透视和...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
MaxCompute75折抢购
Loading...NodeJs&环境下&Koa&框架试验&&之二
上回说到怎样将Koa这个web框架运行在NodeJs环境中呢?我们来将上次写的那个hell.js 内容改成如下:
var koa = require('koa');
var app = koa();
app.use(function *(){
& this.body = 'Hello World';
app.listen(8888);
&& 注意:现在你直接在命令行中运行:node hello.js
是会报错的。错误一般如下:
function *respond(next){
SyntaxError: Unexpected token *
Module._compile (module.js:439:25)
Object.Module._extensions..js (module.js:474:10)
Module.load (module.js:356:32)
Function.Module._load (module.js:312:12)
Module.require (module.js:364:17)
&&& at require
(module.js:380:17)
&&& at Object.
(C:\Program Files\nodejs\node_modules\koa\index.js:2:1
Module._compile (module.js:456:26)
Object.Module._extensions..js (module.js:474:10)
Module.load (module.js:356:32)
&& 这是因为&
app.use(function *(){ 语句中有一个 * ,这种方式被称为generator functions
,一般写作function *(){...} 的形式,在此类function
中可以支持ES6的一种yield概念(什么?你不知道什么是yield...%$#@%....呵呵,好吧,其实我也不知道。不过我相信,我们后面会遇到它的,请耐心一点。)。于是我们需要让这种新型的javascript方法可以编译通过,就需要在运行node
命令的时候加上一个harmony参数(嗯,你知道什么是河蟹吧。呵呵,对了。harmony的英文意思就是和谐,就是为了让编译器不仅可以接纳旧的javascript语法也可以接纳新时代的语法。)语句如下:
node --harmony hello.js
&& 好了,你已经看出来了。Koa 在
原生态的NodeJs的基础上进行了一番进化。从程序员的角度来看,首先变得更加简洁、易读了;然后,其实是最重要的一个进化:“使用 koa
编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升常用错误处理效率。Koa
不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。 ”
&& 下一回我们就尝试着用这个东东做一个web应用吧。
&& 哦,提醒一下,最好使用最新的NodeJs
v0.11.4。在命令行下查一下你的版本就可以知道了。
&& NodeJs v0.11.4下载地址:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。标签:至少1个,最多5个
上图是一个典型的采用 Node.js 开发 web 应用的前后端结构,下面介绍一下 Node 服务层在其中的作用以及使用 Node.js 的一些优劣。
Node 服务层作用:
传统做法是后端提供 api 供前端直接调用,但后端逐渐趋于服务化,直接调用面临的问题有:
数据需要二次加工
后端服务部署在内网时,前端无法直接调用
使用 Node.js 的优势:
前后端分离,节省沟通、联调成本。
生态圈繁荣,第三方模块很多,合理使用可以大量提升开发效率。
处理高并发场景性能更高,适合 web 应用。
使用 Node.js 的劣势:
js 是弱类型语言,可靠性不高,潜在问题很难发现。
不适合 CPU 密集型的应用,如视频编解码。
Node.js 框架介绍
提到 Node.js 开发,不得不提目前炙手可热的2大框架 Express 和 Koa。
Express 诞生已有时日, 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,主要基于 Connect 中间件,并且自身封装了路由、视图处理等功能,使用人数众多。
Koa 相对更为年轻, 是 Express 原班人马基于 ES6 新特性重新开发的框架,主要基于 co 中间件,框架自身不包含任何中间件,很多功能需要借助第三方中间件解决,但是由于其基于 ES6 generator 特性的异步流程控制,解决了 "callback hell" 和麻烦的错误处理问题,大受开发者欢迎。Koa 目前正式版本是 1.2.4,Koa 团队表示 2.0 版本需要 node 支持 async/await 时才会发布。
Hello World
两者创建一个基础的 Web 服务都非常简单,写法也基本相同,最大的区别是路由处理 Express 是自身集成的,而 Koa 需要引入中间件。
// Express
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
app.listen(3000)
var koa = require('koa')
var route = require('koa-route')
var app = koa()
app.use(route.get('/', function *(){
this.body = 'Hello World'
app.listen(3000)
Express 自身集成了视图功能,提供了 consolidate.js 功能,支持几乎所有 JavaScript 模板引擎,并提供了视图设置的便利方法。
Koa 需要引入 co-views 中间件。
// Express
var express = require('express')
var app = express()
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.get('/', function (req, res) {
res.render('index', {
title: 'bilibili'
var koa = require('koa')
var route = require('koa-route')
var views = require('co-views')
var render = views(__dirname + '/views', {
default: "jade"
var app = koa()
app.use(route.get('/', function *() {
this.body = yield render('index', {
title: 'bilibili'
HTTP Request
两个框架都封装了HTTP Request对象,有一点不同是 Koa v1 使用 this 取代 Express 的 req、res。
// Express
var app = require('express')()
app.get('/room/:id', function (req, res) {
console.log(req.params)
// 获取POST数据需要 body-parser 中间件
var bodyParser = require('body-parser')
app.use(bodyParser.json())
app.post('/sendgift', function (req, res) {
console.log(req.body)
var app = require('koa')()
var route = require('koa-route')
app.use(route.get('/room/:id', function *() {
console.log(this.req.query)
// 获取POST数据需要 co-body 中间件
var parse = require('co-body')
app.use(route.post('/sendgift', function *() {
var post = yield parse(this.request)
console.log(post)
Express 和 Koa 的区别
异步流程控制
Express 采用 callback 来处理异步,Koa v1 采用 generator,Koa v2 采用 async/await。
下面分别对 js 当中 callback、promise、generator、async/await 这四种异步流程控制进行了对比,generator 和 async/await 使用同步的写法来处理异步,明显好于 callback 和 promise,async/await 在语义化上又要比 generator 更强。
// callback
var api1 = '/api/characters/583'
var api2 = '/api/characters/584'
function fetchData () {
type: 'GET',
url: api1,
dataType: 'json',
success: function (data1) {
type: 'GET',
url: api2,
dataType: 'json',
success: function (data2) {
console.log(`${data1.name} and ${data2.name} are two characters in Game of Thrones`)
fetchData()
// Promise
var api1 = '/api/characters/583'
var api2 = '/api/characters/584'
function fetchData () {
fetch(api1).then(res1 =& {
res1.json().then(data1 =& {
fetch(api2).then(res2 =& {
res2.json().then(data2 =& console.log(`${data1.name} and ${data2.name} are two characters in Game of Thrones`))
fetchData()
// generator
var api1 = '/api/characters/583'
var api2 = '/api/characters/584'
function *fetchData () {
var name1 = yield request(api1)
var name2 = yield request(api2)
console.log(`${name1} and ${name2} are two characters in Game of Thrones`)
function request (url) {
fetch(url).then(res =& res.json()).then(data =& it.next(data.name))
var it = fetchData()
// async/await
var api1 = '/api/characters/583'
var api2 = '/api/characters/584'
async function fetchData () {
var name1 = await request(api1)
var name2 = await request(api2)
console.log(`${name1} and ${name2} are two characters in Game of Thrones`)
function request (url) {
return fetch(url).then(res =& res.json()).then(data =& data.name)
fetchData()
Express 使用 callback 捕获异常,对于深层次的异常捕获不了,Koa 使用 try catch,能更好地解决异常捕获。
// Express callback
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
// Koa generator
app.use(function *(next) {
yield next
} catch (err) {
this.status = err.status || 500
this.body = { message: err.message }
this.app.emit('error', err, this)
// Koa async/await
app.use(async (ctx, next) =& {
await next()
} catch (err) {
ctx.status = err.status || 500
ctx.body = { message: err.message }
ctx.app.emit('error', err, this)
优点:线性逻辑,通过中间件形式把业务逻辑细分、简化,一个请求进来经过一系列中间件处理后再响应给用户,清晰明了。
缺点:基于 callback 组合业务逻辑,业务逻辑复杂时嵌套过多,异常捕获困难。
优点:首先,借助 co 和 generator,很好地解决了异步流程控制和异常捕获问题。其次,Koa 把 Express 中内置的 router、view 等功能都移除了,使得框架本身更轻量。
缺点:社区相对较小。
8 收藏&&|&&31
你可能感兴趣的文章
47 收藏,4.1k
26 收藏,1.6k
97 收藏,94.6k
本作品采用 署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
express不一定就是callback,你用co或者async/await也是可以的。。。
express不一定就是callback,你用co或者async/await也是可以的。。。
我还在想怎么能把 callback 当作是 express 的区别 = =
我还在想怎么能把 callback 当作是 express 的区别 = =
@webpack 说的没错,但是异步的异常处理是express永远的痛
@webpack 说的没错,但是异步的异常处理是express永远的痛
分享到微博?
技术专栏,帮你记录编程中的点滴,提升你对技术的理解收藏感兴趣的文章,丰富自己的知识库
明天提醒我
我要该,理由是:Koa (koajs) -- 基于 Node.js 平台的下一代 web 开发框架 | Koajs 中文文档
koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。
Koa 目前需要 &=0.11.x版本的 node 环境。并需要在执行 node 的时候附带 --harmony 来引入 generators 。 如果您安装了较旧版本的 node ,您可以安装
(node版本控制器),来快速安装 0.11.x
$ npm install -g n
$ n 0.11.12
$ node --harmony my-koa-app.js
Koa 应用是一个包含一系列中间件 generator 函数的对象。
这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行。
Koa 类似于其他中间件系统(比如 Ruby's Rack 、Connect 等),
然而 Koa 的核心设计思路是为中间件层提供高级语法糖封装,以增强其互用性和健壮性,并使得编写中间件变得相当有趣。
Koa 包含了像 content-negotiation(内容协商)、cache freshness(缓存刷新)、proxy support(代理支持)和 redirection(重定向)等常用任务方法。
与提供庞大的函数支持不同,Koa只包含很小的一部分,因为Koa并不绑定任何中间件。
任何教程都是从 hello world 开始的,Koa也不例外^_^
var koa = require('koa');
var app = koa();
app.use(function *(){
this.body = 'Hello World';
app.listen(3000);
中间件级联
Koa 的中间件通过一种更加传统(您也许会很熟悉)的方式进行级联,摒弃了以往 node 频繁的回调函数造成的复杂代码逻辑。
我们通过 generators 来实现“真正”的中间件。
Connect 简单地将控制权交给一系列函数来处理,直到函数返回。
与之不同,当执行到 yield next 语句时,Koa 暂停了该中间件,继续执行下一个符合请求的中间件('downstrem'),然后控制权再逐级返回给上层中间件('upstream')。
下面的例子在页面中返回 &Hello World&,然而当请求开始时,请求先经过 x-response-time 和 logging 中间件,并记录中间件执行起始时间。
然后将控制权交给 reponse 中间件。当中间件运行到 yield next 时,函数挂起并将控制前交给下一个中间件。当没有中间件执行 yield next 时,程序栈会逆序唤起被挂起的中间件来执行接下来的代码。
var koa = require('koa');
var app = koa();
// x-response-time
app.use(function *(next){
var start = new D
var ms = new Date -
this.set('X-Response-Time', ms + 'ms');
app.use(function *(next){
var start = new D
var ms = new Date -
console.log('%s %s - %s', this.method, this.url, ms);
// response
app.use(function *(){
this.body = 'Hello World';
app.listen(3000);
应用配置是 app 实例属性,目前支持的配置项如下:
app.name 应用名称(可选项)
app.env 默认为 NODE_ENV 或者 development
app.proxy 如果为 true,则解析 &Host& 的 header 域,并支持 X-Forwarded-Host
app.subdomainOffset 默认为2,表示 .subdomains 所忽略的字符偏移量。
app.listen(...)
Koa 应用并非是一个 1-to-1 表征关系的 HTTP 服务器。
一个或多个Koa应用可以被挂载到一起组成一个包含单一 HTTP 服务器的大型应用群。
如下为一个绑定3000端口的简单 Koa 应用,其创建并返回了一个 HTTP 服务器,为 Server#listen() 传递指定参数(参数的详细文档请查看)。
var koa = require('koa');
var app = koa();
app.listen(3000);
app.listen(...) 实际上是以下代码的语法糖:
var http = require('http');
var koa = require('koa');
var app = koa();
http.createServer(app.callback()).listen(3000);
这意味着您可以同时支持 HTTPS 和 HTTPS,或者在多个端口监听同一个应用。
var http = require('http');
var koa = require('koa');
var app = koa();
http.createServer(app.callback()).listen(3000);
http.createServer(app.callback()).listen(3001);
app.callback()
返回一个适合 http.createServer() 方法的回调函数用来处理请求。
您也可以使用这个回调函数将您的app挂载在 Connect/Express 应用上。
app.use(function)
为应用添加指定的中间件,详情请看
设置签名Cookie密钥,该密钥会被传递给 。
当然,您也可以自己生成 KeyGrip 实例:
app.keys = ['im a newer secret', 'i like turtle'];
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
在进行cookie签名时,只有设置 signed 为 true 的时候,才会使用密钥进行加密:
this.cookies.set('name', 'tobi', { signed: true });
默认情况下Koa会将所有错误信息输出到 stderr,除非 NODE_ENV 是 &test&。为了实现自定义错误处理逻辑(比如 centralized logging),您可以添加 &error& 事件监听器。
app.on('error', function(err){
log.error('server error', err);
如果错误发生在 请求/响应 环节,并且其不能够响应客户端时,Contenxt 实例也会被传递到 error 事件监听器的回调函数里。
app.on('error', function(err, ctx){
log.error('server error', err, ctx);
当发生错误但仍能够响应客户端时(比如没有数据写到socket中),Koa会返回一个500错误(Internal Server Error)。
无论哪种情况,Koa都会生成一个应用级别的错误信息,以便实现日志记录等目的。
Context(上下文)
Koa Context 将 node 的 request 和 response 对象封装在一个单独的对象里面,其为编写 web 应用和 API 提供了很多有用的方法。
这些操作在 HTTP 服务器开发中经常使用,因此其被添加在上下文这一层,而不是更高层框架中,因此将迫使中间件需要重新实现这些常用方法。
context 在每个 request 请求中被创建,在中间件中作为接收器(receiver)来引用,或者通过 this 标识符来引用:
app.use(function *(){
// is the Context
this. // is a koa Request
this. // is a koa Response
许多 context 的访问器和方法为了便于访问和调用,简单的委托给他们的 ctx.request 和 ctx.response 所对应的等价方法,
比如说 ctx.type 和 ctx.length 代理了 response 对象中对应的方法,ctx.path 和 ctx.method 代理了 request 对象中对应的方法。
Context 详细的方法和访问器。
Node 的 request 对象。
Node 的 response 对象。
Koa 不支持 直接调用底层 res 进行响应处理。请避免使用以下 node 属性:
res.statusCode
res.writeHead()
res.write()
ctx.request
Koa 的 Request 对象。
ctx.response
Koa 的 Response 对象。
应用实例引用。
ctx.cookies.get(name, [options])
获得 cookie 中名为 name 的值,options 为可选参数:
'signed': 如果为 true,表示请求时 cookie 需要进行签名。
注意:Koa 使用了 Express 的
模块,options 参数只是简单地直接进行传递。
ctx.cookies.set(name, value, [options])
设置 cookie 中名为 name 的值,options 为可选参数:
signed: 是否要做签名
expires: cookie 有效期时间
path: cookie 的路径,默认为 /'
domain: cookie 的域
secure: false 表示 cookie 通过 HTTP 协议发送,true 表示 cookie 通过 HTTPS 发送。
httpOnly: true 表示 cookie 只能通过 HTTP 协议发送
注意:Koa 使用了 Express 的
模块,options 参数只是简单地直接进行传递。
ctx.throw(msg, [status])
抛出包含 .status 属性的错误,默认为 500。该方法可以让 Koa 准确的响应处理状态。
Koa支持以下组合:
this.throw(403)
this.throw('name required', 400)
this.throw(400, 'name required')
this.throw('something exploded')
this.throw('name required', 400) 等价于:
var err = new Error('name required');
err.status = 400;
注意:这些用户级错误被标记为 err.expose,其意味着这些消息被准确描述为对客户端的响应,而并非使用在您不想泄露失败细节的场景中。
ctx.respond
为了避免使用 Koa 的内置响应处理功能,您可以直接赋值 this.repond =。如果您不想让 Koa 来帮助您处理 reponse,而是直接操作原生 res 对象,那么请使用这种方法。
注意: 这种方式是不被 Koa 支持的。其可能会破坏 Koa 中间件和 Koa 本身的一些功能。其只作为一种 hack 的方式,并只对那些想要在 Koa 方法和中间件中使用传统 fn(req, res) 方法的人来说会带来便利。
Request aliases
以下访问器和别名与
ctx.header
ctx.method
ctx.method=
ctx.originalUrl
ctx.query=
ctx.querystring
ctx.querystring=
ctx.hostname
ctx.socket
ctx.protocol
ctx.secure
ctx.subdomains
ctx.accepts()
ctx.acceptsEncodings()
ctx.acceptsCharsets()
ctx.acceptsLanguages()
Response aliases
以下访问器和别名与
ctx.status
ctx.status=
ctx.length=
ctx.length
ctx.headerSent
ctx.redirect()
ctx.attachment()
ctx.remove()
ctx.lastModified=
请求(Request)
Koa Request 对象是对 node 的 request 进一步抽象和封装,提供了日常 HTTP 服务器开发中一些有用的功能。
请求头对象
req.method
req.method=
设置请求方法,在实现中间件时非常有用,比如 methodOverride()。
req.length
以数字的形式返回 request 的内容长度(Content-Length),或者返回 undefined。
获得请求url地址。
设置请求地址,用于重写url地址时。
req.originalUrl
获取请求原始地址。
获取请求路径名。
设置请求路径名,并保留请求参数(就是url中?后面的部分)。
req.querystring
获取查询参数字符串(url中?后面的部分),不包含 ?。
req.querystring=
设置查询参数。
获取查询参数字符串,包含 ?。
设置查询参数字符串。
获取 host (hostname:port)。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。
req.hostname
获取 hostname。当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。
获取请求 Content-Type,不包含像 &charset& 这样的参数。
var ct = this.request.
// =& &image/png&
req.charset
获取请求 charset,没有则返回 undefined:
this.request.charset
// =& &utf-8&
将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象。
注意:该方法不支持嵌套解析。
比如 &color=blue&size=small&:
color: 'blue',
size: 'small'
req.query=
根据给定的对象设置查询参数字符串。
注意:该方法不支持嵌套对象。
this.query = { next: '/login' };
检查请求缓存是否 &fresh&(内容没有发生变化)。该方法用于在 If-None-Match / ETag, If-Modified-Since 和 Last-Modified 中进行缓存协调。当在 response headers 中设置一个或多个上述参数后,该方法应该被使用。
this.set('ETag', '123');
// cache is ok
if (this.fresh) {
this.status = 304;
// cache is stale
// fetch new data
this.body = yield db.find('something');
与 req.fresh 相反。
req.protocol
返回请求协议,&https& 或者 &http&。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。
req.secure
简化版 this.protocol == &https&,用来检查请求是否通过 TLS 发送。
请求远程地址。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。
当 X-Forwarded-For 存在并且 app.proxy 有效,将会返回一个有序(从 upstream 到 downstream)ip 数组。
否则返回一个空数组。
req.subdomains
以数组形式返回子域名。
子域名是在host中逗号分隔的主域名前面的部分。默认情况下,应用的域名假设为host中最后两部分。其可通过设置 app.subdomainOffset 进行更改。
举例来说,如果域名是 &tobi.&:
如果没有设置 app.subdomainOffset,其 subdomains 为 [&ferrets&, &tobi&]。
如果设置 app.subdomainOffset 为3,其 subdomains 为 [&tobi&]。
req.is(type)
检查请求所包含的 &Content-Type& 是否为给定的 type 值。
如果没有 request body,返回 undefined。
如果没有 content type,或者匹配失败,返回 false。
否则返回匹配的 content-type。
// With Content-Type: text/ charset=utf-8
this.is('html'); // =& 'html'
this.is('text/html'); // =& 'text/html'
this.is('text/*', 'text/html'); // =& 'text/html'
// When Content-Type is application/json
this.is('json', 'urlencoded'); // =& 'json'
this.is('application/json'); // =& 'application/json'
this.is('html', 'application/*'); // =& 'application/json'
this.is('html'); // =& false
比如说您希望保证只有图片发送给指定路由:
if (this.is('image/*')) {
// process
this.throw(415, 'images only!');
Content Negotiation
Koa request 对象包含 content negotiation 功能(由
req.accepts(types)
req.acceptsEncodings(types)
req.acceptsCharsets(charsets)
req.acceptsLanguages(langs)
如果没有提供 types,将会返回所有的可接受类型。
如果提供多种 types,将会返回最佳匹配类型。如果没有匹配上,则返回 false,您应该给客户端返回 406 &Not Acceptable&。
为了防止缺少 accept headers 而导致可以接受任意类型,将会返回第一种类型。因此,您提供的类型顺序非常重要。
req.accepts(types)
检查给定的类型 types(s) 是否可被接受,当为 true 时返回最佳匹配,否则返回 false。type 的值可以是一个或者多个 mime 类型字符串。
比如 &application/json& 扩展名为 &json&,或者数组 [&json&, &html&, &text/plain&]。
// Accept: text/html
this.accepts('html');
// =& &html&
// Accept: text/*, application/json
this.accepts('html');
// =& &html&
this.accepts('text/html');
// =& &text/html&
this.accepts('json', 'text');
// =& &json&
this.accepts('application/json');
// =& &application/json&
// Accept: text/*, application/json
this.accepts('image/png');
this.accepts('png');
// =& false
// Accept: text/*;q=.5, application/json
this.accepts(['html', 'json']);
this.accepts('html', 'json');
// =& &json&
// No Accept header
this.accepts('html', 'json');
// =& &html&
this.accepts('json', 'html');
// =& &json&
this.accepts() 可以被调用多次,或者使用 switch:
switch (this.accepts('json', 'html', 'text')) {
case 'json':
case 'html':
case 'text':
default: this.throw(406, 'json, html, or text only');
req.acceptsEncodings(encodings)
检查 encodings 是否可以被接受,当为 true 时返回最佳匹配,否则返回 false。
注意:您应该在 encodings 中包含 identity。
// Accept-Encoding: gzip
this.acceptsEncodings('gzip', 'deflate', 'identity');
// =& &gzip&
this.acceptsEncodings(['gzip', 'deflate', 'identity']);
// =& &gzip&
当没有传递参数时,返回包含所有可接受的 encodings 的数组:
// Accept-Encoding: gzip, deflate
this.acceptsEncodings();
// =& [&gzip&, &deflate&, &identity&]
注意:如果客户端直接发送 q=0 时,identity encoding(表示no encoding) 可以不被接受。虽然这是一个边界情况,您仍然应该处理这种情况。
req.acceptsCharsets(charsets)
检查 charsets 是否可以被接受,如果为 true 则返回最佳匹配, 否则返回 false。
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
this.acceptsCharsets('utf-8', 'utf-7');
// =& &utf-8&
this.acceptsCharsets(['utf-7', 'utf-8']);
// =& &utf-8&
当没有传递参数时, 返回包含所有可接受的 charsets 的数组:
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
this.acceptsCharsets();
// =& [&utf-8&, &utf-7&, &iso-8859-1&]
req.acceptsLanguages(langs)
检查 langs 是否可以被接受,如果为 true 则返回最佳匹配,否则返回 false。
// Accept-Language:q=0.8, es, pt
this.acceptsLanguages('es', 'en');
// =& &es&
this.acceptsLanguages(['en', 'es']);
// =& &es&
当没有传递参数时,返回包含所有可接受的 langs 的数组:
// Accept-Language:q=0.8, es, pt
this.acceptsLanguages();
// =& [&es&, &pt&, &en&]
req.idempotent
检查请求是否为幂等(idempotent)。
req.socket
返回请求的socket。
req.get(field)
返回请求 header 中对应 field 的值。
响应(Response)
Koa Response 对象是对 node 的 response 进一步抽象和封装,提供了日常 HTTP 服务器开发中一些有用的功能。
Response header 对象。
res.socket
Request socket。
res.status
获取 response status。不同于 node 在默认情况下 res.statusCode 为200,res.status 并没有赋值。
res.statusString
Response status 字符串。
res.status=
通过 数字状态码或者不区分大小写的字符串来设置response status:
100 &continue&
101 &switching protocols&
102 &processing&
201 &created&
202 &accepted&
203 &non-authoritative information&
204 &no content&
205 &reset content&
206 &partial content&
207 &multi-status&
300 &multiple choices&
301 &moved permanently&
302 &moved temporarily&
303 &see other&
304 &not modified&
305 &use proxy&
307 &temporary redirect&
400 &bad request&
401 &unauthorized&
402 &payment required&
403 &forbidden&
404 &not found&
405 &method not allowed&
406 &not acceptable&
407 &proxy authentication required&
408 &request time-out&
409 &conflict&
410 &gone&
411 &length required&
412 &precondition failed&
413 &request entity too large&
414 &request-uri too large&
415 &unsupported media type&
416 &requested range not satisfiable&
417 &expectation failed&
418 &i'm a teapot&
422 &unprocessable entity&
423 &locked&
424 &failed dependency&
425 &unordered collection&
426 &upgrade required&
428 &precondition required&
429 &too many requests&
431 &request header fields too large&
500 &internal server error&
501 &not implemented&
502 &bad gateway&
503 &service unavailable&
504 &gateway time-out&
505 &http version not supported&
506 &variant also negotiates&
507 &insufficient storage&
509 &bandwidth limit exceeded&
510 &not extended&
511 &network authentication required&
注意:不用担心记不住这些字符串,如果您设置错误,会有异常抛出,并列出该状态码表来帮助您进行更正。
res.length=
通过给定值设置 response Content-Length。
res.length
如果 Content-Length 作为数值存在,或者可以通过 res.body 来进行计算,则返回相应数值,否则返回 undefined。
获得 response body。
设置 response body 为如下值:
string written
Buffer written
Stream piped
Object json-stringified
null no content response
如果 res.status 没有赋值,Koa会自动设置为 200 或 204。
Content-Type 默认为 text/html 或者 text/plain,两种默认 charset 均为 utf-8。 Content-Length 同时会被设置。
Content-Type 默认为 application/octet-stream,Content-Length同时被设置。
Content-Type 默认为 application/octet-stream。
Content-Type 默认为 application/json。
res.get(field)
获取 response header 中字段值,field 不区分大小写。
var etag = this.get('ETag');
res.set(field, value)
设置 response header 字段 field 的值为 value。
this.set('Cache-Control', 'no-cache');
res.set(fields)
使用对象同时设置 response header 中多个字段的值。
this.set({
'Etag': '1234',
'Last-Modified': date
res.remove(field)
移除 response header 中字段 filed。
获取 response Content-Type,不包含像 &charset& 这样的参数。
var ct = this.
// =& &image/png&
通过 mime 类型的字符串或者文件扩展名设置 response Content-Type
this.type = 'text/ charset=utf-8';
this.type = 'image/png';
this.type = '.png';
this.type = 'png';
注意:当可以根据 res.type 确定一个合适的 charset 时,charset 会自动被赋值。
比如 res.type = 'html' 时,charset 将会默认设置为 &utf-8&。然而当完整定义为 res.type = 'text/html'时,charset 不会自动设置。
res.redirect(url, [alt])
执行 [302] 重定向到对应 url。
字符串 &back& 是一个特殊参数,其提供了 Referrer 支持。当没有Referrer时,使用 alt 或者 / 代替。
this.redirect('back');
this.redirect('back', '/index.html');
this.redirect('/login');
this.redirect('');
如果想要修改默认的 [302] 状态,直接在重定向之前或者之后执行即可。如果要修改 body,需要在重定向之前执行。
this.status = 301;
this.redirect('/cart');
this.body = 'Redirecting to shopping cart';
res.attachment([filename])
设置 &attachment& 的 Content-Disposition,用于给客户端发送信号来提示下载。filename 为可选参数,用于指定下载文件名。
检查 response header 是否已经发送,用于在发生错误时检查客户端是否被通知。
res.lastModified
如果存在 Last-Modified,则以 Date 的形式返回。
res.lastModified=
以 UTC 格式设置 Last-Modified。您可以使用 Date 或 date 字符串来进行设置。
this.response.lastModified = new Date();
设置 包含 &s 的 ETag。注意没有对应的 res.etag 来获取其值。
this.response.etag = crypto.createHash('md5').update(this.body).digest('hex');
res.append(field, val)
在 header 的 field 后面 追加 val。
res.vary(field)
相当于执行res.append('Vary', field)。
Community links to discover third-party middleware for Koa, full runnable examples,
thorough guides and more! If you have questions join us in IRC!
以下列出了更多第三方提供的 koa 中间件、完整实例、全面的帮助文档等。如果有问题,请加入我们的 IRC!
#koajs on freenode}

我要回帖

更多关于 node.js koa 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信