KOA知识点

Koa 是一个新的 web 框架 , 致力于成为 web 应用 和 API 开发 领域中的一个更小、更富有 表现力、更健壮的基石。

koa是Express的下一代基于Node.js的web框架

koa2完全使⽤用Promise并配合async来实现异步

Koa中间件机制:Koa中间件机制就是函数式 组合概念 Compose的概念,将一组需要顺序执⾏的 函数复合为一个函数,外层函数的参数实际是内层函数的返回值。洋葱圈模型可以形象表示这种机 制

中间件机制、请求、响应处理

const Koa = require('koa')
const app = new Koa()
app.use((ctx, next) => {
  ctx.body = [
    {
    	name: 'tom'
    }
  ]
  next()
})

app.use((ctx, next) => {
console.log('url' + ctx.url)
  if (ctx.url === '/html') {
    ctx.type = 'text/html;charset=utf-8'
    ctx.body = `<b>我的名字是:${ctx.body[ 0 ].name}</b>`
  }
})
app.listen( 3000 )

常见的中间件操作:

静态服务

app.use(require('koa-static')(__dirname + '/'))

路由

const router = require('koa-router')()
router.get('/string', async (ctx, next) => {
		ctx.body = 'koa2 string'
})
router.get('/json', async (ctx, next) => {
    ctx.body = {
    		title: 'koa2 json'
    }
})
app.use(router.routes())

日志:

app.use(async (ctx,next) => {
    const start = new Date().getTime()
    console.log(`start: ${ctx.url}`);
    await next();
    const end = new Date().getTime()
    console.log(`请求${ctx.url}, 耗时${parseInt(end-start)}ms`)
})

koa 原理:一个基于node.js的入门级http服务

const http = require('http')
const server = http.createServer((req, res)=>{
    res.writeHead(200)
    res.end('hi tom')
})

server.listen(3000,()=>{
		console.log('监听端口3000')
})

koa的目标是⽤用更简单化、流程化、模块化的方式实现回调部分

// 创建bg.js
const http = require("http");

class BG {
    listen(...args) {
        const server = http.createServer((req, res) => {
        		this.callback(req, res);
    		});
    		server.listen(...args);
    }
    use(callback) {
    		this.callback = callback;
    }
}
module.exports = BG;

// 调⽤,app.js
const BG = require("./bg");
const app = new BG();

app.use((req, res) => {` `
res.writeHead( 200 );
res.end("ok");
});

app.listen( 3000 , () => {
console.log("监听端口3000");
});

context

koa为了能够简化API,引入上下文context概念,将原始请求对象req和响应对象res封装并挂载到context上,并且在context上设置getter和setter,从而简化操作。

// app.js
app.use(ctx=>{
		ctx.body = 'hehe'
})
const context = require("./context");
const request = require("./request");
const response = require("./response");

class BG{
    listen(...args) {
        const server = http.createServer((req, res) => {
        // 创建上下⽂文
        let ctx = this.createContext(req, res);
        this.callback(ctx)
        // 响应
        res.end(ctx.body);
    });
    // ...
    }
		// 构建上下⽂, 把res和req都挂载到ctx之上,并且在ctx.req和ctx.request.req同时保存
		createContext(req, res) {
        const ctx = Object.create(context);
        ctx.request = Object.create(request);
        ctx.response = Object.create(response);
        ctx.req = ctx.request.req = req;
        ctx.res = ctx.response.res = res;
        return ctx;
    }
}

常见koa中间件的实现

koa中间件的规范:

  • 一个async函数

  • 接收ctx和next两个参数

  • 任务结束需要执⾏行行next

  • 中间件常见任务:

    • 请求拦截

    • 路由

    • 日志

    • 静态文件服务

class BG {
    // 初始化中间件数组
    constructor() {
        this.middlewares = [];
    }
    listen(...args) {
        const server = http.createServer(async (req, res) => {
            const ctx = this.createContext(req, res);
            // 中间件合成
            const fn = this.compose(this.middlewares);
            // 执⾏合成函数并传⼊上下⽂
            await fn(ctx);
            res.end(ctx.body);
        });
        server.listen(...args);
    }
    use(middleware) {
        // 将中间件加到数组⾥
        this.middlewares.push(middleware);
    }
    // 合成函数
    compose(middlewares) {
        return function(ctx) { // 传⼊上下⽂
            return dispatch( 0 );
            function dispatch(i) {
                let fn = middlewares[i];
                if (!fn) {
                    return Promise.resolve();
                }
                return Promise.resolve(
                    fn(ctx, function next() {// 将上下文传入中间件,					mid(ctx,next)
                        return dispatch(i + 1 );
                    })
                );
            }
        };
    }
		createContext(req, res) {
        let ctx = Object.create(context);
        ctx.request = Object.create(request);
        ctx.response = Object.create(response);
        ctx.req = ctx.request.req = req;
        ctx.res = ctx.response.res = res;
        return ctx;
    }
}
module.exports = BG;

routes()的返回值是一个中间件,由于需要用到method,所以需要挂载method到ctx之上,修改request.js

// request.js
module.exports = {
    // add...
    get method(){
    	return this.req.method.toLowerCase()
    }
}

// context.js
module.exports = {
	// add...
    get method() {
    	return this.request.method
    },
}

class Router {
    constructor() {
    	this.stack = [];
    }

    register(path, methods, middleware) {
        let route = {path, methods, middleware}
        this.stack.push(route);
    }
    get(path,middleware){
        this.register(path, 'get', middleware);
    }
    post(path,middleware){
    	this.register(path, 'post', middleware);
    }
    routes() {
    	let stock = this.stack;
   	 	return async function(ctx, next) {
    		let currentPath = ctx.url;
    		let route;

    		for (let i = 0 ; i < stock.length; i++) {
    			let item = stock[i];
    			if (currentPath === item.path && item.methods.indexOf(ctx.method) >= 0 ) {
                    // 判断path和method
                    route = item.middleware;
                    break;
    			}
    		}

            if (typeof route === 'function') {
                route(ctx, next);
                return;
            }

    		await next();
    	};
    }
}
module.exports = Router;

 使用:

const Koa = require('./bg')
const Router = require('./router')
const app = new Koa()
const router = new Router();

router.get('/index', async ctx => {
	console.log('index,xx')
	ctx.body = 'index page';
});
router.get('/post', async ctx => { ctx.body = 'post page'; });
router.get('/list', async ctx => { ctx.body = 'list page'; });

router.post('/index', async ctx => { ctx.body = 'post page'; });

// 路由实例输出父中间件 router.routes()
app.use(router.routes());

app.listen( 3000 ,()=>{
		console.log('server runing')
})
  • 静态⽂文件服务koa-static

    • 配置绝对资源⽬目录地址,默认为static

    • 获取⽂文件或者⽬目录信息

    • 静态⽂文件读取

    • 返回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值