工程实践
koa的原理与koa-static koa-router等中间件的实现
koa的原理与洋葱模型 koa是什么 express原班人马开发的极简web框架,为什么称为极简,因为只做了4件事 处理HTTP的request 处理http的response 中间件的加载 中间件的执行 所以我们在使用koa开发时,只需要做两件事:1、框架的设计2、中间件的选择 koa的文件结构 application.js 封装了context,request,response,中间件处理流程
koa的原理与洋葱模型 koa是什么 express原班人马开发的极简web框架,为什么称为极简,因为只做了4件事 处理HTTP的request 处理http的response 中间件的加载 中间件的执行 所以我们在使用koa开发时,只需要做两件事:1、框架的设计2、中间件的选择 koa的文件结构 application.js 封装了context,request,response,中间件处理流程
koa是什么
express原班人马开发的极简web框架,为什么称为极简,因为只做了4件事
所以我们在使用koa开发时,只需要做两件事:1、框架的设计2、中间件的选择
koa的文件结构
koa的异步处理
koa是基于async/await操作中间件,node版本需要大于7 他是async/await generator/yield的衍生,但本质还是Promise
koa的AOP设计

代码实现
let context = {}
async function m1(ctx,next){
console.log('1')
await next();
console.log('2')
}
async function m2(ctx,next){
console.log('3')
await next();
console.log('4')
}
async function m3(ctx,next){
console.log('5')
await next();
console.log('6')
}
Promise.resolve(m1(context,async()=>{
return Promise.resolve(m2(context,async()=>{
return Promise.resolve(m3(context,async()=>{
return Promise.resolve();
}))
}))
})).then(()=>{
console.log("end");
})
输出的值分别是 1 3 5 6 4 2 ,其中生命周期就是Promise 中间件是m1 m2 m3 next前为前置操作,next后为后置操作,类似一个大回环,先前置操作的最后后置操作,就是这个道理
上篇博客里已经介绍了koa如何开启服务器,这里面就不说了,可以看上篇nodejs熟悉,http,fs,path,Buffer的使用
// log.js
function log(ctx) {
console.log(ctx)
}
module.exports = function () {
return async function (ctx, next) {
log(ctx)
await next()
}
}
// index.js
const Koa = require("koa");
const Log = require("./logger");
const app = new Koa();
app.use(Log())
app.use((ctx)=>{
ctx.body = "hello world"
})
app.listen(1111)
const Koa = require("koa");
const fs = require("fs")
const app = new Koa();
function render(page) {
return new Promise((resolve, reject) => {
let ViewUrl = `./test/${page}`;
fs.readFile(ViewUrl, 'binary', (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
async function route(url) {
let view = "404.html"
switch (url) {
case "/":
view = 'index.html';
break;
default:
view = view;
break;
}
let html = await render(url);
return html;
}
app.use(async (ctx) => {
let url = ctx.request.url;
let html = await route(url);
ctx.body = html;
})
app.listen(1111);
const Koa = require("koa");
const fs = require("fs");
const app = new Koa();
const Router = require("koa-router");
// 子路由1
let home = new Router();
home.get("/", async (ctx) => {
ctx.body = "<h1>hello Router</>";
})
// 子路由2
let page = new Router();
page.get("/page1", async (ctx) => {
ctx.body = "page1"
}).get("/page2", async (ctx) => {
ctx.body = "page2"
})
// 装载路由
let router = new Router();
router.use('/', home.routes(), home.allowedMethods())
router.use('/page', page.routes(), page.allowedMethods())
// 加载路由中间件
app.use(router.routes()).use(router.allowedMethods())
app.listen(1111)
const Koa = require("koa");
const app = new Koa();
app.use( async (ctx)=>{
let url = ctx.url;
let query = ctx.request.query;
let querystring = ctx.request.querystring;
let _query = ctx.query;
let _querystring = ctx.querystring;
ctx.body = {
url,
query,
querystring,
_query,
_querystring
}
})
app.listen(1111)
function parsePostData(ctx) {
return new Promise((resolve, reject) => {
try {
let postdata = "";
ctx.req.addListener('data', (data) => {
postdata += data
})
ctx.req.addListener('end', () => {
let parseData = parseQuery(postdata);
resolve(parseData)
})
} catch (err) {
reject(err)
}
})
}
function parseQuery(queryStr) {
let queryData = {};
let queryStrList = queryStr.split("&");
for (let [index, queryStr] of queryStrList.entries()) {
let itemList = queryStr.split("=");
queryData[itemList[0]] = decodeURIComponent(itemList[1])
}
return queryData
}
const Koa = require("koa");
const app = new Koa();
app.use(async (ctx) => {
if (ctx.method == "GET") {
let html = `
<h1>koa2 request post demo</h1>
<form method="POST" action="/">
<p>userName</p>
<input name="userName" /><br/>
<p>nickName</p>
<input name="nickName" /><br/>
<p>email</p>
<input name="email" /><br/>
<button type="submit">submit</button>
</form>`
ctx.body = html;
}else if(ctx.method=='POST'){
let postData = await parsePostData(ctx);
ctx.body = postData;
}
})
app.listen(1111)
const Koa = require("koa");
const app = new Koa();
const bodyParser = require("koa-bodyparser");
app.use(bodyParser());
app.use(async (ctx) => {
if (ctx.method == "GET") {
let html = `
<form method="POST" action="/">
<p>userName</p>
<input name="userName" /><br/>
<p>nickName</p>
<input name="nickName" /><br/>
<p>email</p>
<input name="email" /><br/>
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if (ctx.method == "POST") {
let postData = ctx.request.body
ctx.body = postData;
}
})
app.listen(1111)
const Koa = require('koa');
const path = require("path");
const fs = require("fs");
const url = require("url");
const app = new Koa();
// 静态文件夹相对入口文件的位置
const staticPath = "./static";
// 定义文件类型
let mimes = {
'css': 'text/css',
'less': 'text/css',
'gif': 'image/gif',
'html': 'text/html',
'ico': 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'json': 'application/json',
'pdf': 'application/pdf',
'png': 'image/png',
'svg': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
'tiff': 'image/tiff',
'txt': 'text/plain',
'wav': 'audio/x-wav',
'wma': 'audio/x-ms-wma',
'wmv': 'video/x-ms-wmv',
'xml': 'text/xml'
}
// 读取目录内容
function walk(reqPath) {
let files = fs.readdirSync(reqPath);
let dirList = [];
let fileList = [];
for (let i = 0; i < files.length; i++) {
let item = files[i];
let itemArr = item.split("\.");
let itemMime = (itemArr.length > 1) ? itemArr[itemArr.length - 1] : "undefined";
if (typeof mimes[itemMime] === "undefined") {
dirList.push(files[i]);
} else {
fileList.push(files[i])
}
}
let result = dirList.concat(fileList);
return result;
}
// 封装目录内容
function dir(url, reqPath) {
let contentList = walk(reqPath);
let html = "";
for (let [index, item] of contentList.entries()) {
html += `<li><a href="${url==='/'?'':url}/${item}">${item}</a></li>`
}
return "<ul>" + html + "<ul/>"
}
// 读取文件方法
function file(filePath) {
let content = fs.readFileSync(filePath, 'binary');
return content;
}
// 获取静态文件内容
async function content(ctx, fullStaticPath) {
let reqPath = path.join(fullStaticPath, ctx.url);
let exist = fs.existsSync(reqPath);
let content = "";
if (!exist) {
content = "404";
} else {
let stat = fs.statSync(reqPath);
if (stat.isDirectory()) {
content = dir(ctx.url, reqPath);
} else {
content = await file(reqPath);
}
}
return content;
}
// 解析请求内容
function parseMime(url) {
let extName = path.extname(url);
extName = extName ? extName.slice(1) : "unknown";
return mimes[extName]
}
// 使用中间件
app.use(async (ctx) => {
let fullStaticPath = path.join(__dirname, staticPath);
let _content = await content(ctx, fullStaticPath);
let _mime = parseMime(ctx.url)
if (_mime) {
ctx.type = _mime;
}
if (_mime && _mime.indexOf("image/") >= 0) {
ctx.res.writeHead(200)
ctx.res.write(_content, 'binary')
ctx.res.end();
} else {
ctx.body = _content;
}
})
app.listen(1111);
const Koa = require("koa");
const path = require("path");
const static = require("koa-static");
const app = new Koa();
const staticPath = "./static"
app.use(static(
path.join(__dirname, staticPath)
))
app.use((ctx) => {
ctx.body = "hello "
})
app.listen(1111)
暂无评论
确认操作
请再次确认编辑图片
待上传图片 (剩余 0 张)
项目详情
确认评论邮箱
邀请制评论