Koa 框架

一、基本用法

安装:

npm install --save koa

用 Koa 架设一个 HTTP 服务,在app.js 输入以下内容:

const Koa = require('koa');
const app = new Koa();

app.listen(3000);

运行这个脚本。

node app.js

打开浏览器,访问 http://127.0.0.1:3000 。你会看到页面显示"Not Found",表示没有发现任何内容。这是因为我们并没有告诉 Koa 应该显示什么内容。


Not found
二、中间件middleware

app.use() 用来加载中间件。use 里面必须放入函数。基本上,Koa 所有的功能都是通过中间件实现的,每个中间件默认接受两个参数,第一个参数是 Context (ctx)对象,第二个参数是 next (放行函数)函数。只要调用 next 函数,就可以把执行权转交给下一个中间件。
看一下 next 的放行顺序:

const Koa = require('koa');
const app = new Koa();
app.use((ctx,next)=>{
    console.log(">>one");
    next().then(()=>{console.log("one OK")});
    console.log("<<one");
});
app.use((ctx,next)=>{
    console.log(">>two");
    next().then(()=>{console.log("two OK")});
    console.log("<<two");
});
app.use((ctx,next)=>{
    console.log(">>three");
    console.log("<<three");
});

app.listen(3000);
// ========放行顺序
>>one
>>two
>>three
<<three
<<two
<<one
two OK
one OK

不写 async 的时候 next 是异步的最后执行。
异步中间件:基本上所有的中间件都是同步的,不包含异步操作。如果有异步操作(比如读取数据库),中间件就必须写成 async 函数

写上 async next 就变成同步执行语句了。

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx,next)=>{
    console.log(">>one");
    await next().then(()=>{console.log("one OK")});
    console.log("<<one");
});
app.use((ctx,next)=>{
    console.log(">>two");
    next().then(()=>{console.log("two OK")});
    console.log("<<two");
});
app.use((ctx,next)=>{
    console.log(">>three");
    console.log("<<three");
});

app.listen(3000);
// ========放行顺序
>>one
>>two
>>thre
<<thre
<<two
two OK
one OK
<<one

中间件之间的联系:

const Koa = require('koa');
const app = new Koa();

app.use(async (ctx,next)=>{
    console.log(1);
    await next().then((res)=>{console.log(res)});
});
app.use((ctx,next)=>{
    console.log(2);
    return 9999;
});

app.listen(3000);

输出结果:1 2 9999,第二个中间件可以返回内容给第一个中间件。

三、返回给用户的内容

使用 app.use 方法加载 ctx.response.body(或 ctx.body) 返回内容。ctx.response 代表 HTTP Response。同样地,ctx.request 代表 HTTP Request。

const Koa = require('koa');
const app = new Koa();

app.use(function(ctx){
    ctx.response.body = 'Hello World';
});
app.listen(3000);
ctx.response

Koa 默认的返回类型是text/plain,如果想返回其他类型的内容,可以先用ctx.request.accepts判断一下,客户端希望接受什么数据(根据 HTTP Request 的Accept字段),然后使用ctx.response.type指定返回类型。

const Koa = require('koa');
const app = new Koa();

app.use(function(ctx){
    if(ctx.response.type = 'html'){
        ctx.response.body = '<h1>Hello World</h1>';
    }
});
app.listen(3000);
四、网页模板
const fs = require("fs");
const Koa = require('koa');
const app = new Koa();

app.use(function(ctx){
    ctx.response.type = 'html';
    ctx.response.body = fs.createReadStream('./template.html');
});
app.listen(3000);
网页模板
五、原生路由
const fs = require('fs');
const Koa = require('koa');
const app = new Koa();

app.use(function(ctx){
    if(ctx.request.path == '/template'){
        ctx.response.type = 'html';
        ctx.response.body = fs.createReadStream('./template.html');
    }else{
        ctx.response.body = '路径不正确!';
    }
});
app.listen(3000);
原生路由
六、原生路由用起来不太方便,我们可以使用封装好的koa-route模块

安装模块:

npm install --save koa-route

改写原生路由配置:

const fs = require('fs');
const Koa = require('koa');
const route = require('koa-route');
const app = new Koa();

app.use(route.get('/template',function(ctx){
    ctx.response.type = 'html';
    ctx.response.body = fs.createReadStream('./template.html');
}));
app.listen(3000);

执行效果:


七、 静态资源

如果网站提供静态资源(图片、字体、样式表、脚本......),为它们一个个写路由就很麻烦,也没必要。koa-static模块封装了这部分的请求。请看下面的例子
安装依赖:

npm install --save koa-static

从首页开始静态化文件路径:

const fs = require('fs');
const Koa = require('koa');
const route = require('koa-route');
const app = new Koa();
const path = require('path');
const serve = require('koa-static');
app.use(serve(path.join(__dirname)));

app.listen(3000);
静态化文件路径

单独制定某一个目录进行静态化:

app.use(serve(path.join(__dirname, './static')));
八、 重定向

有些场合,服务器需要重定向(redirect)访问请求。比如,用户登陆以后,将他重定向到登陆前的页面。ctx.response.redirect() 方法可以发出一个302跳转,将用户导向另一个路由。

九、错误处理

如果代码运行过程中发生错误,我们需要把错误信息返回给用户。HTTP 协定约定这时要返回500状态码。Koa 提供了ctx.throw()方法,用来抛出错误,ctx.throw(500)就是抛出500错误。

const fs = require('fs');
const Koa = require('koa');
const app = new Koa();
app.use((ctx,next)=>{
    ctx.throw(500);
});

app.listen(3000);
错误处理

如果将ctx.response.status设置成404,就相当于ctx.throw(404),返回404错误浏览器显示404页面"Page Not Found"。

十、error 事件的监听

运行过程中一旦出错,Koa 会触发一个error事件。监听这个事件,也可以处理错误。
Koa 框架 -- JavaScript 标准参考教程(alpha)

const Koa = require('koa');
const app = new Koa();
app.use((ctx,next)=>{
    ctx.throw(500);
});
app.on('error', (err, ctx) => console.error('server error', err));
app.listen(3000);

访问 http://127.0.0.1:3000 ,你会在命令行窗口看到"server error xxx"。

需要注意的是,如果错误被 try...catch 捕获,就不会触发 error 事件。这时,必须调用ctx.app.emit('error', err, ctx);,手动释放 error 事件,才能让监听函数生效。

十一、cookie
const Koa = require('koa');
const app = new Koa();
app.use((ctx, next) => {
    const n = Number(ctx.cookies.get('view') || 0) + 1;
    ctx.cookies.set('view', n);
    ctx.response.body = n + ' views';
});
app.listen(3000);

访问 http://127.0.0.1:3000 ,你会看到1 views。刷新一次页面,就变成了2 views。再刷新,每次都会计数增加1。

十二、表单

表单处理,表单就是 POST 方法发送到服务器的键值对。koa-body 模块可以用来从 POST 请求的数据体里面提取键值对。koa-body 模块还可以用来处理文件上传。

安装依赖:

npm install koa-body --save

表单代码:

const Koa = require('koa');
const app = new Koa();

const koaBody = require('koa-body');

app.use(koaBody());
app.use(function(ctx) {
    const body = ctx.request.body;
    console.log(ctx.request);//{ name: 'Hero' }
    if (!body.name) ctx.throw(400, '什么也没有!');
    ctx.body = {
        name: body.name
    };
});
app.listen(3000);

使用 curl 命令行工具进行测试。windows下使用curl命令&&常用curl命令 - 苍青浪 - 博客园

在 curl.exe 文件夹打开另一个命令行窗口,运行下面的命令。
输入:curl -X POST --data "name=hero" 127.0.0.1:3000
得到:{"name":"hero"}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容