Koa 框架教程
作者: 阮一峰
日期: 2017年8月 9日
Node 主要用在开发 Web 应用。这决定了使用 Node,往往离不开 Web 应用框架。
Koa 就是一种简单好用的 Web 框架。它的特点是优雅、简洁、表达力强、自由度高。本身代码只有1000多行,所有功能都通过插件实现,很符合 Unix 哲学。
本文从零开始,循序渐进,教会你如何使用 Koa 写出自己的 Web 应用。每一步都有简洁易懂的示例,希望让大家一看就懂。
零、准备
首先,检查 Node 版本。
Koa 必须使用 7.6 以上的版本。如果你的版本低于这个要求,就要先升级 Node。
然后,克隆本文的配套示例库。(如果不方便使用 Git,也可以下载 zip 文件解压。)
接着,进入示例库,安装依赖。
所有示例源码,都在 demos 目录下面。
一、基本用法
1.1 架设 HTTP 服务
只要三行代码,就可以用 Koa 架设一个 HTTP 服务。
运行这个脚本。
打开浏览器,访问 http://127.0.0.1:3000 。你会看到页面显示"Not Found",表示没有发现任何内容。这是因为我们并没有告诉 Koa 应该显示什么内容。
1.2 Context 对象
Koa 提供一个 Context 对象,表示一次对话的上下文(包括 HTTP 请求和 HTTP 回复)。通过加工这个对象,就可以控制返回给用户的内容。
Context.response.body
属性就是发送给用户的内容。请看下面的例子(完整的代码看这里)。
上面代码中,main
函数用来设置ctx.response.body
。然后,使用app.use
方法加载main
函数。
你可能已经猜到了,ctx.response
代表 HTTP Response。同样地,ctx.request
代表 HTTP Request。
运行这个 demo。
访问 http://127.0.0.1:3000 ,现在就可以看到"Hello World"了。
1.3 HTTP Response 的类型
Koa 默认的返回类型是text/plain
,如果想返回其他类型的内容,可以先用ctx.request.accepts
判断一下,客户端希望接受什么数据(根据 HTTP Request 的Accept
字段),然后使用ctx.response.type
指定返回类型。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,现在看到的就是一个 XML 文档了。
1.4 网页模板
实际开发中,返回给用户的网页往往都写成模板文件。我们可以让 Koa 先读取模板文件,然后将这个模板返回给用户。请看下面的例子(完整代码看这里)。
运行这个 Demo。
访问 http://127.0.0.1:3000 ,看到的就是模板文件的内容了。
二、路由
2.1 原生路由
网站一般都有多个页面。通过ctx.request.path
可以获取用户请求的路径,由此实现简单的路由。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000/about ,可以看到一个链接,点击后就跳到首页。
2.2 koa-route 模块
原生路由用起来不太方便,我们可以使用封装好的koa-route
模块。请看下面的例子(完整代码看这里)。
上面代码中,根路径/
的处理函数是main
,/about
路径的处理函数是about
。
运行这个 demo。
访问 http://127.0.0.1:3000/about ,效果与上一个例子完全相同。
2.3 静态资源
如果网站提供静态资源(图片、字体、样式表、脚本......),为它们一个个写路由就很麻烦,也没必要。koa-static
模块封装了这部分的请求。请看下面的例子(完整代码看这里)。
运行这个 Demo。
访问 http://127.0.0.1:3000/12.js,在浏览器里就可以看到这个脚本的内容。
2.4 重定向
有些场合,服务器需要重定向(redirect)访问请求。比如,用户登陆以后,将他重定向到登陆前的页面。ctx.response.redirect()
方法可以发出一个302跳转,将用户导向另一个路由。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000/redirect ,浏览器会将用户导向根路由。
三、中间件
3.1 Logger 功能
Koa 的最大特色,也是最重要的一个设计,就是中间件(middleware)。为了理解中间件,我们先看一下 Logger (打印日志)功能的实现。
最简单的写法就是在main
函数里面增加一行(完整代码看这里)。
运行这个 Demo。
访问 http://127.0.0.1:3000 ,命令行就会输出日志。
3.2 中间件的概念
上一个例子里面的 Logger 功能,可以拆分成一个独立函数(完整代码看这里)。
像上面代码中的logger
函数就叫做"中间件"(middleware),因为它处在 HTTP Request 和 HTTP Response 中间,用来实现某种中间功能。app.use()
用来加载中间件。
基本上,Koa 所有的功能都是通过中间件实现的,前面例子里面的main
也是中间件。每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next
函数。只要调用next
函数,就可以把执行权转交给下一个中间件。
运行这个 demo。
访问 http://127.0.0.1:3000 ,命令行窗口会显示与上一个例子相同的日志输出。
3.3 中间件栈
多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行。
请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,命令行窗口会有如下输出。
如果中间件内部没有调用next
函数,那么执行权就不会传递下去。作为练习,你可以将two
函数里面next()
这一行注释掉再执行,看看会有什么结果。
3.4 异步中间件
迄今为止,所有例子的中间件都是同步的,不包含异步操作。如果有异步操作(比如读取数据库),中间件就必须写成 async 函数。请看下面的例子(完整代码看这里)。
上面代码中,fs.readFile
是一个异步操作,必须写成await fs.readFile()
,然后中间件必须写成 async 函数。
运行这个 demo。
访问 http://127.0.0.1:3000 ,就可以看到模板文件的内容。
3.5 中间件的合成
koa-compose
模块可以将多个中间件合成为一个。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,就可以在命令行窗口看到日志信息。
四、错误处理
4.1 500 错误
如果代码运行过程中发生错误,我们需要把错误信息返回给用户。HTTP 协定约定这时要返回500状态码。Koa 提供了ctx.throw()
方法,用来抛出错误,ctx.throw(500)
就是抛出500错误。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000,你会看到一个500错误页"Internal Server Error"。
4.2 404错误
如果将ctx.response.status
设置成404,就相当于ctx.throw(404)
,返回404错误。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,你就看到一个404页面"Page Not Found"。
4.3 处理错误的中间件
为了方便处理错误,最好使用try...catch
将其捕获。但是,为每个中间件都写try...catch
太麻烦,我们可以让最外层的中间件,负责所有中间件的错误处理。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,你会看到一个500页,里面有报错提示 {"message":"Internal Server Error"}
。
4.4 error 事件的监听
运行过程中一旦出错,Koa 会触发一个error
事件。监听这个事件,也可以处理错误。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,你会在命令行窗口看到"server error xxx"。
4.5 释放 error 事件
需要注意的是,如果错误被try...catch
捕获,就不会触发error
事件。这时,必须调用ctx.app.emit()
,手动释放error
事件,才能让监听函数生效。请看下面的例子(完整代码看这里)。
上面代码中,main
函数抛出错误,被handler
函数捕获。catch
代码块里面使用ctx.app.emit()
手动释放error
事件,才能让监听函数监听到。
运行这个 demo。
访问 http://127.0.0.1:3000 ,你会在命令行窗口看到logging error
。
五、Web App 的功能
5.1 Cookies
ctx.cookies
用来读写 Cookie。请看下面的例子(完整代码看这里)。
运行这个 demo。
访问 http://127.0.0.1:3000 ,你会看到1 views
。刷新一次页面,就变成了2 views
。再刷新,每次都会计数增加1。
5.2 表单
Web 应用离不开处理表单。本质上,表单就是 POST 方法发送到服务器的键值对。koa-body
模块可以用来从 POST 请求的数据体里面提取键值对。请看下面的例子(完整代码看这里)。
运行这个 demo。
打开另一个命令行窗口,运行下面的命令。
上面代码使用 POST 方法向服务器发送一个键值对,会被正确解析。如果发送的数据不正确,就会收到错误提示。
2.3 文件上传
koa-body
模块还可以用来处理文件上传。请看下面的例子(完整代码看这里)。
运行这个 demo。
打开另一个命令行窗口,运行下面的命令,上传一个文件。注意,/path/to/file
要更换为真实的文件路径。
六、参考链接
(完)
文档信息
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
- 发表日期:
- 更多内容: 档案 » JavaScript
- 文集:《前方的路》,《未来世界的幸存者》
- 社交媒体:aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqsVc9rE0EU/mZ3dhPNJl2bVIk/Km09aFBE8GLvnrwJXvwLxIsgCP4Fnit6E8Gb0IMHwUsL9SSNgiAoooJIpE1Joo1h82uT7IxvxmRN3Q32kAdvdrI773vfe+/bDTu9WioDcDAda3Ja8piepQ1avCkCeny0Y+R9KenKwOmHHLvPaKn7AtVOoO8dOWDCMpg+41gMQv5FNEJACgoE8MsPNLDBhgfoutMOsJDmWLmU037C4TApciljwQ/kHoohQxV06+wMXNvE7WINuaSpvdYVKLgWnl3O4zAxU3Z1IYVGT+B5qYWV9z2kbQaT/cOwTsxOUUYF+mB5Dkmi8HG3h2q9hxsFNwRTdvQgxxnXRrMvIdkEhllis/qtiWuLDm4WZnBlPoWnXz28LHdw0uGR7m9Wu3j0qYGEubfn4UlBfXO4gTZltRNMg9w9f0i7kNFxllsBlS0x75gYfxyWTBUjT2W5CSMSPBrQuG21+hiMDS8CeCzF8eSLp13uQ3Ab1IqMFZN8tFHPmgOBF99bYP8Be1Xp6t7OJszJgKpPSiZvaj7uf2hguz2IBQuozDvFH6RDBjuK9wdQDvt0nMpW+8efGyh5UcAeZb2+UcHbnz5Jx4wdlp4yJYU3kLiQtfBwOYeLc8nIwfXtNu69q2Oz4mMxbemYOOOjKarhvq51KUjg3GwiFPIuvcNF6pnSnWK0lOEabNLgQh1aJFAhlGB9rG110B2+oyRNPc0sZbRNFltmLKDKqj4Qrm1ojzOxDz2pyPQ0P7CK4c40/wJ+CzAAGYrXsvfFXR4AAAAASUVORK5CYII=" alt="" /> twitter,aaarticlea/png;base64,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" alt="" /> weibo
相关文章
- 2018.07.08: Web Worker 使用教程一、概述
- 2018.07.04: 浏览器数据库 IndexedDB 入门教程一、概述
- 2018.06.18: JavaScript 的 this 原理一、问题的由来 学懂 JavaScript 语言,一个标志就是理解下面两种写法,可能有不一样的结果。
- 2018.03.20: Node 调试工具入门教程JavaScript 程序越来越复杂,调试工具的重要性日益凸显。客户端脚本有浏览器,Node 脚本怎么调试呢?
广告(购买广告位)
留言(92条)
阮荣军 说:
passport 官网 http://www.passportjs.org/
alisx 说:
在5.2的代码示例中第4行
------------------
1 // demos/20.js
2 const koaBody = require('koa-body');
3
4 const main = async function(ctx) {
5 const body = ctx.request.body;
6 if (!body.name) ctx.throw(400, '.name required');
7 ctx.body = { name: body.name };
8 };
-------------------
main 是个异步方法,但从代码来看,没有异步的过程,请问
1 是否没有必要声明 async
2 是否出于未来代码变更考虑,将所有的方法都声明为 async,这样是好还是不好?会有性能或其他问题吗?
谢谢!
IndraNyo 说:
重定向这里
ctx.response.redirect('/');
ctx.response.body = 'Index Page';
第二行好像不执行 已经重定向走了 应该在 route.get('/', XXX)的route里写 才会输出吧
还是我操作不对?请老师指教
hooper 说:
多此一举