用Node.js开发Web服务器端,有几个显著的优点:
速度快,很是快!这得益于Node.js天生是异步的。
好消息是这个教程已经帮你选好了,你只须要跟着教程一条道走到黑就能够了。
koa是Express的下一代基于Node.js的web框架,目前有1.x和2.0两个版本。建议用2.0
Express是第一代最流行的web框架,它对Node.js的http进行了封装
var
express =
require
(
'express'
);
var
app = express(); app.get(
'/'
,
function
(req, res) { res.send(
'Hello World!'
); }); app.listen(
3000
,
function
() { console.log(
'Example app listening on port 3000!'
); });
koa2的代码看上去像这样:
app.
use
(async (ctx, next) => { await next();
var
data = await doReadFile(); ctx.response.type =
'text/plain'
; ctx.response.body = data; });
koa入门
如何安装koa2
能够用npm命令直接安装koa。先打开命令提示符,务必把当前目录切换到
文件所在的那个
目录,而后执行命令:
npm install koa
@2
.
0
.
0
任什么时候候均可以直接删除整个
node_modules
目录,由于用
npm install
命令能够完整地从新下载全部依赖。而且,这个目录不该该被放入版本控制中。
或者经过下面方式安装:
建立一个
package.json
,这个文件描述了咱们的
hello-koa
工程会用到哪些包
{ "
name
":
"hello-koa2"
, "
version
":
"1.0.0"
, "
description
":
"Hello Koa 2 example with async"
, "
main
":
"app.js"
, "
scripts
": { "
start
":
"node app.js"
}, "
keywords
": [
"koa"
,
"async"
], "
author
":
"Michael Liao"
, "
license
":
"Apache-2.0"
, "
repository
": { "
type
":
"git"
, "
url
":
"https://github.com/michaelliao/learn-javascript.git"
}, "
dependencies
": { "
koa
":
"2.0.0"
} }
其中,
dependencies
描述了咱们的工程依赖的包以及版本号。其余字段均用来描述项目信息,
可任意填写。
而后,咱们在
hello-koa
目录下执行
npm install
就能够把所需包以及依赖包一次性所有装好:
npm start
命令会让npm执行定义在
package.json
文件中的start对应命令
// 导入koa,和koa 1.x不一样,在koa2中,咱们导入的是一个class,所以用大写的Koa表示:
const
Koa =
require
(
'koa'
);
// 建立一个Koa对象表示web app自己:
const
app =
new
Koa();
// 对于任何请求,app将调用该
异步函数
处理请求:
app.
use
(async (ctx, next) => { await next(); ctx.response.type =
'text/html'
; ctx.response.body =
'<h1>Hello, koa2!</h1>'
; });
// 在端口3000监听:
app.listen(
3000
); console.log(
'app started at port 3000...'
);
其中,参数
ctx
是由koa传入的
封装了request和response的变量
,咱们能够经过它访问request和response,
next
是koa传入的将要处理的下一个异步函数。
async
标记的函数称为异步函数,在异步函数中,能够用
await
调用另外一个异步函数,这两个关键字将在ES7中引入。
每收到一个http请求,koa就会调用经过
app.use()
注册的async函数,并传入
ctx
和
next
参数。
为何要调用
await next()
?
缘由是koa把不少async函数组成一个处理链,每一个async函数均可以作一些本身的事情,而后用
await next()
来调用下一个async函数。咱们把每一个async函数称为middleware,这些middleware能够组合起来,完成不少有用的功能。
console.log(`${ctx.request.method} ${ctx.request.url}`);
// 打印URL
const
ms =
new
Date().getTime() - start;
// 耗费时间
console.log(`Time: ${ms}ms`);
// 打印耗费时间
若是一个middleware没有调用
await next()
,会怎么办?答案是后续的middleware将再也不执行了。
例如,一个检测用户权限的middleware能够决定是否继续处理请求,仍是直接返回403错误:
app.use(async (ctx,
next
) => {
if
(await checkUserPermission(ctx)) { await
next
(); }
else
{ ctx.response.status =
403
; } });
处理url路由
"koa-router": "7.0.0"
const
Koa = require(
'koa'
);
// 注意require('koa-router')返回的是函数:
const
router = require(
'koa-router'
)();
const
app =
new
Koa();
// log request URL:
app.use(async (ctx, next) => { console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); await next(); });
// add url-route:
router.get(
'/hello/:name'
, async (ctx, next) => {
var
name =
ctx.params.name;
ctx.response.body = `<h1>Hello, ${name}!
</h1>
`; });
router.get
('/', async (ctx, next) => { ctx.response.body = '
<h1>
Index
</h1>
'; }); // add router middleware: app.use(router.routes()); app.listen(3000); console.log('app started at port 3000...');
注意导入
koa-router
的语句最后的
()
是函数调用:
处理post请求
能够用
router.post('/path', async ...
注意:
须要引入另外一个middleware来解析原始request请求,而后,把解析后的参数,绑定到
ctx.request.body
中。
"koa-bodyparser": "3.2.0"
const
bodyParser =
require
(
'koa-bodyparser'
);
在合适的位置加上:
app.
use
(bodyParser());
因为middleware的顺序很重要,这个
koa-bodyparser
必须在
router
以前被注册到
app
对象上。
name = ctx.request.body.name || '', //
默认值
把URL处理函数集中到某几个js文件中
好比 在
controllers
目录下编写
index.js
:
var fn_index = async (ctx, next) => { ctx.response.body = `
<h1>
Index
</h1>
<form
action
=
"/signin"
method
=
"post"
>
<p>
Name:
<input
name
=
"name"
value
=
"koa"
></p>
<p>
Password:
<input
name
=
"password"
type
=
"password"
></p>
<p><input
type
=
"submit"
value
=
"Submit"
></p>
</form>
`; };
...
module.exports = { 'GET /': fn_index, 'POST /signin': fn_signin };
另外一个
var
fn_hello = async (ctx, next) => {
var
name = ctx.params.name; ctx.response.body = `<h1>Hello, ${name}!
</h1>
`; }; module.exports = { 'GET /hello/:name': fn_hello };
修改
app.js
,让它自动扫描
controllers
目录,找到全部
js
文件,导入,而后注册每一个URL:
let
命令,用来声明变量。它的用法相似于
var
,可是所声明的变量,只在
let
命令所在的代码块内有效。
for
循环的计数器,就很合适使用
let
命令。
const
fs =
require
(
'fs'
);
function
addMapping
(router, mapping) {
for
(
var
url
in
mapping) {
if
(url.startsWith(
'GET '
)) {
var
path = url.substring(
4
); router.get(path, mapping[url]); console.log(`register URL mapping: GET ${path}`); }
else
if
(url.startsWith(
'POST '
)) {
var
path = url.substring(
5
); router.post(path, mapping[url]); console.log(`register URL mapping: POST ${path}`); }
else
{ console.log(`invalid URL: ${url}`); } } }
function
addControllers
(router) {
var
files = fs.readdirSync(__dirname +
'/controllers'
);
var
js_files = files.filter((f) => {
return
f.endsWith(
'.js'
); });
for
(
var
f of js_files) { console.log(`process controller: ${f}...`);
let
mapping = require(__dirname +
'/controllers/'
+ f); addMapping(router, mapping); } } //addControllers(router);
module.exports =
function
(dir) { let controllers_dir = dir ||
'controllers'
,
// 若是不传参数,扫描目录默认为'controllers'
router =
require
(
'koa-router'
)(); addControllers(router,
controllers_dir
);
return
router.routes(); };
主文件中
// 导入controller middleware:
const
controller =
require
(
'./controller'
); ...
// 使用middleware:
app.
use
(controller());
其它:
Nunjucks
模板引擎