KOA笔记

封装了http,特点是中间件和错误处理

用法

let koa = require('koa')
let app = new koa()

app.use(async (ctx,next)=>{ // 洋葱模型  // 1
  console.log('第1个开始');
  let t = await next()
  console.log(t);
  return '第1个结束'
});
app.use(async (ctx,next)=>{   // 2
  console.log('第2个开始');
  await logger();
  let t = next()
  console.log(t);
  return '第2个结束'
});
app.use(async (ctx,next)=>{ // 3
  console.log('第3个开始');
  //next();
  ctx.body = 'ok';
  return '第3个结束'
});
app.listen(3000); 

中间件的特点是洋葱模型(为保运行结果在预期内,尽量使用async函数)

简单实现

// mykoa.js
let http = require('http')
let content = require('./context')
let stream = require('stream')

class mykoa {
    constructor () { 
        this.middlewares = []
        this.server = http.createServer(this.Handler.bind(this))
    }

    async compose (ctx) {
        // 以洋葱模型执行中间件
        let t = this.middlewares.reduceRight((prev, fn) => {
            return async () => {
                if (prev.is_called == 'yes') { 
                    throw new Error('next 只能调用一次')
                }
                prev.is_called = 'yes'
                return await fn(ctx, prev)
            }
        }, () => {});
        await t();
    }

    async Handler (req, res) {
        let ctx = {}
        try {
            content.call(ctx, req, res)
            // 处理中间件
            await this.compose(ctx)
            
            if (ctx.body) {
                // console.log('** end **')
                res.statusCode = 200;
                if (ctx.body instanceof stream) {  // body里是流当做下载
                    res.setHeader("Content-Disposition","attachment;filename="+encodeURI('下载'));
                    ctx.body.pipe(res)
                } else {
                    res.end(ctx.body)
                }
            } 
            else throw new Error('body is empty')

        } catch (e) {
            console.error(e)
            res.statusCode = 404;
            res.end('Not Find')
        }
    }

    use (fn) {
        this.middlewares.push(fn)
    }

    listen (port) {
        this.server.listen(port)
    }
}

module.exports = mykoa
// context.js 添加koa自有参数
module.exports = function (req, res) {
    this.req = req
    this.res = res
    this.request = Object.create(req)
    this.response = Object.create(res)  // 链上多套一层
    this.url = req.url
    let _body = null
    let attributes = {
        get () { return _body },
        set (val) { _body = val; }
    }
    Object.defineProperty(this.response, 'body', attributes)
    Object.defineProperty(this, 'body', attributes)

    if (req.method == 'POST') {
        res.setHeader('Content-Type', 'application/json;charset=utf-8')
    } else if (req.method == 'Get') {
        res.setHeader('Content-Type', 'text/html;charset=utf8')
    }
}

常用包

  • koa-bodyParser
  • koa-static
  • koa-views
  • koa-router
  • koa-generator koa脚手架
  • koa mypro -e 创建一个ejs项目

你可能感兴趣的:(KOA笔记)