KOA笔记

作者: 我叫Aliya但是被占用了 | 来源:发表于2019-07-16 23:09 被阅读0次

    封装了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笔记

          本文链接:https://www.haomeiwen.com/subject/vzbxlctx.html