【Koa系列】10min快速入门Koa
简介
koa是基于node开发的一个服务端框架,功能同express,但更小巧简单。
官方仓库地址:https://github.com/koajs/koa
创建项目
创建文件夹nodeKoa,执行以下脚本
npm init -y
npm i koa
npm i nodemon
基础示例
创建一个服务器
命令行输入
nodemon app.js
打开浏览器,输入http:localhost:3000即可看到效果
路由
koa没有提供路由模块,我们可以借助其内置的ctx.path获取其请求路径,自己做出判断
//创建一个请求
app.use( ctx => {const path = ctx.pathif(path == "/"){ctx.body = "这是首页"}else if( path == "/foo"){ctx.body = "这是详情页"}else{ctx.body = "404"}
})
但是,这种方式还是比较麻烦的,我们使用它的官方route插件
官方地址:https://github.com/koajs/router
npm install @koa/router
基础示例
/*** 使用koa启动一个HTTP服务*/
const Koa = require("koa")const Router = require("@koa/router")
//创建实例
const app = new Koa()const router = new Router()router.get("/",ctx => {ctx.body = '这是首页'
})//路由挂载
app.use(router.routes()).use(router.allowedMethods());app.listen(3000, () => {console.log("服务运行在:http:localhost:3000");
})
路由模块的写法和expresss几乎是一致的
静态资源托管
如果网站提供静态资源(图片、字体什么的),如果为他们单独写一个路由很麻烦也没有必要。koa-stati模块封装了这部分请求
官方文档:https://github.com/koajs/static
安装
npm install koa-static
我们在根目录创建一个public文件夹,里面放一张图片,然后直接访问里面的内容
可以发现,资源文件无法直接访问,我们创建一个静态资源目录
/*** 使用koa启动一个HTTP服务*/
const Koa = require("koa")
const Router = require("@koa/router")
//引入静态资源插件
const static = require("koa-static")//创建实例
const app = new Koa()
//建立静态托管目录
app.use(static("./public"))const router = new Router()router.get("/",ctx => {ctx.body = '这是首页'
})//路由挂载
app.use(router.routes()).use(router.allowedMethods());app.listen(3000, () => {console.log("服务运行在:http:localhost:3000");
})
核心代码
//引入静态资源插件
const static = require("koa-static")
//建立静态托管目录
app.use(static("./public"))
这时,可以发现资源已经可以被正常访问了
我们目前的路径是相对路径,这是不安全的,我们应该使用绝对路径.
const path = require('path')
//建立静态托管目录
app.use(static(path.join(__dirname,"./public")))
虚拟路径
资源的目录或中间件可以设置成虚拟路径,需要使用官方的mount中间件
传送门: https://github.com/koajs/mount
安装
npm install koa-mount
使用
const mount = require('koa-mount')
//建立静态托管目录
app.use( mount('/public',static(path.join(__dirname,"./public"))))
路由重定向
请求bar路径,重定向到boo
router.get('/bar',ctx => {//重定向针对的同步请求ctx.redirect('/boo')
)
中间件
koa最大的特色,就是中间件.为了理解中间件.我们先看一下logger(日志功能)的实现
- 先进后出
- 最外层首先执行
- 调用next,把执行权交给下一个中间件最内层的中间件最后执行
logger功能
/*** 使用koa启动一个HTTP服务*/
const Koa = require("koa")//创建实例
const app = new Koa()const one = (ctx,next) => {console.log(">>> one");next()console.log("<<< one");
}const two = (ctx,next) => {console.log(">>> two");next()console.log("<<< two");
}const three = (ctx,next) => {console.log(">>> three");next()console.log("<<< three");
}app.use(one)
app.use(two)
app.use(three)app.listen(3000, () => {console.log("服务运行在:http:localhost:3000");
})
输出结果
>>> one
>>> two
>>> three
<<< three
<<< two
<<< one
异步中间件
/*** 使用koa启动一个HTTP服务*/
const Koa = require("koa")//创建实例
const app = new Koa()const fs = require('fs')const util = require("util")app.use( async (ctx ,next) => {const asyReadFile = util.promisify(fs.readFile)const data = await asyReadFile("./index.html","utf8")ctx.body = data
})app.listen(3000, () => {console.log("服务运行在:http//:localhost:3000");
})
除了在回调函数里指定类型,我们也可以在ctx里直接指定返回的类型
app.use( async (ctx ,next) => {const asyReadFile = util.promisify(fs.readFile)const data = await asyReadFile("./index.html")ctx.type = "html"ctx.body = data
})
Koa的中间件合并
当有多个中间件时,我们一个个进行挂载是非常低效的,我们可以使用中间件合并功能。
传送门:https://github.com/koajs/compose
安装
npm install koa-compose
示例
app.use = compose([a1, a2, a3, ...])
中间件异常处理
正常情况,我们捕获一个错误可能会这么写代码
const Koa = require("koa")
//创建实例
const app = new Koa()
app.use( ctx => {try {JSON.parse("dsssssss")ctx.body = "hello koa"}catch(err){ctx.response.status = 500ctx.response.body = "服务端内部错误"}
})
app.listen(3000, () => {console.log("服务运行在:http://localhost:3000");
})
koa也给我们提供了内置函数简化500的错误响应
app.use( ctx => {try {JSON.parse("dsssssss")ctx.body = "hello koa"}catch(err){ctx.throw(500)}
})
对于多个异常,我们可以借助koa的洋葱模型进行捕获,用最外层的中间件进行异常捕获,内层的中间件异常最终全部会被koa最外层的中间件所捕获。
const Koa = require("koa");
//创建实例
const app = new Koa();
app.use(async (ctx, next) => {try {await next();} catch (err) {console.log(111);ctx.response.status = 500;ctx.body = "服务器内部错误";}
});
app.use((ctx) => {console.log(222);JSON.parse("dsssssss");ctx.body = "hello koa";
});app.listen(3000, () => {console.log("服务运行在:http://localhost:3000");
});
最外层的中间件函数必须写成async的形式,不然异常不会被捕获进去