koa2框架使用心得

文章目录

  • 一、express和koa2的区别
  • 二、安装koa2
    • 1、使用脚手架
    • 2、路由
    • 3、ctx
  • 三、中间件
  • 四、session
    • 1、使用 koa-generic-session 和 koa-redis
    • 2、req.session 保存登录信息到redis
    • 3、登录校验做成express中间件
  • 五、日志
    • 1、 access日志使用,使用morgan
  • 六、完整app.js
  • 七、模拟中间件

一、express和koa2的区别

  • express中间件是异步回调,koa2原生支持async/await
  • 新开发框架和系统,都开始基于koa2,例如egg.js
  • express虽然未过时,但是koa2肯定是未来趋势

二、安装koa2

1、使用脚手架

npm i -g koa-generator
Koa2 koa2-test # 初始化项目

2、路由

const router = require('koa-router')()
router.prefix('/api')
router.get('/', async (ctx, next) => {
  await ctx.render('index', {
    title: 'Hello Koa 2!'
  })
})

router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})

router.get('/json', async (ctx, next) => {
  ctx.body = {
    title: 'koa2 json'
  }
})

module.exports = router
app.use(index.routes(), index.allowedMethods());

3、ctx

ctx 可以看做req、和res的集合体

router.get('/bar', function (ctx, next) {
  	ctx.request.body;//请求参数体
    ctx.query;//请求参数
    ctx.session;//获取session
    ctx.cookie;
    ctx.cookies.get(name, [options]);
    ctx.cookies.set(name, value, [options]);
    ctx.body={};//返回参数体
})

三、中间件

// logger
// 记录下面几个路由用的时间
app.use(async (ctx, next) => {
    const start = new Date()
    await next()
    const ms = new Date() - start
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

// routes
app.use(index.routes(), index.allowedMethods());
app.use(users.routes(), users.allowedMethods());
app.use(user.routes(), user.allowedMethods());
app.use(blog.routes(), blog.allowedMethods());

四、session

1、使用 koa-generic-session 和 koa-redis

yarn add  koa-generic-session  koa-redis redis
app.js

//session
const session = require('koa-generic-session');
const redisStore = require('koa-redis');
const {REDIS_CONF} = require('./conf/db');

//session配置 在注册路由之前写
app.keys = ['DSDSDsds890809'];
app.use(session({
    //配置cookie
    cookie: {
        path: '/',
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000
    },
    //配置redis
    store: redisStore({
        all: `${REDIS_CONF.host}:${REDIS_CONF.port}`
    })
}));
测试:
router.get('/session-test', async function (ctx, next) {
    let session = ctx.session;
    if (session.vievCount == null) {
        session.vievCount = 0;
    }
    session.vievCount++;
    ctx.body = session.vievCount
});

2、req.session 保存登录信息到redis

redis.js

const redis = require('redis')
const {REDIS_CONF} = require('../conf/db')

//创建客户端
let redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host);
redisClient.on('error', err => {
    console.log(err)
});
module.exports = redisClient
app.js

let RedisStore = require('connect-redis')(session);

let redisClient = require('./db/redis');
let sessionStore = new RedisStore({
    client: redisClient
});

app.use(session({
    secret: 'asdXXnkj_asdnsk_90789_sad',
    cookie: {
        path: '/',//默认
        httpPnly: true,//默认
        maxAge: 24 * 60 * 60 * 1000
    },
    store: sessionStore
})); // 处理session

3、登录校验做成express中间件

loginCheck.js

const {SuccessModel, ErrorModel} = require('../model/resModel');

module.exports = (re, res, next) => {
    if (require.session.username) {
        next()
    } else {
        res.json(new ErrorModel("未登录"))
    }
}

路由里面:

blog.js

const loginCheck = require('../middleware/loginCheck')

router.post('/new', loginCheck, (req, res, next) => {
    req.body.author = req.session.username
    const result = newBlog(req.body)
    return result.then(data => {
        res.json(
            new SuccessModel(data)
        )
    })
})

五、日志

1、 access日志使用,使用morgan

yarn add koa-morgan
app.js


//日志
const path = require('path');
const fs = require('fs');
const morgan = require('koa-morgan');

//日志记录
const ENV = process.env.NODE_ENV
if (ENV !== 'production') {
    // 开发环境 / 测试环境
    app.use(morgan('dev'));
} else {
    // 线上环境
    const logFileName = path.join(__dirname, 'logs', 'access.log')
    const writeStream = fs.createWriteStream(logFileName, {
        flags: 'a'
    })
    app.use(morgan('combined', {
        stream: writeStream
    }));
}

六、完整app.js

const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger');

//session
const session = require('koa-generic-session');
const redisStore = require('koa-redis');
const {REDIS_CONF} = require('./conf/db');

//路由
const index = require('./routes/index')
const users = require('./routes/users')
const user = require('./routes/my/user')
const blog = require('./routes/my/blog')

//日志
const path = require('path');
const fs = require('fs');
const morgan = require('koa-morgan');

// error handler
onerror(app)

// middlewares
app.use(bodyparser({
    enableTypes: ['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
    extension: 'pug'
}))

// logger
app.use(async (ctx, next) => {
    await next();
    let rt = ctx.response.get('X-Response-Time');
    console.log(`${ctx.method} ${ctx.url} - ${rt}`)
})

app.use(async (ctx, next) => {
    const start = new Date();
    await next();
    const ms = new Date() - start;
    ctx.set('X-Response-Time', `${ms}ms`)
})

//日志记录
const ENV = process.env.NODE_ENV
if (ENV !== 'production') {
    // 开发环境 / 测试环境
    app.use(morgan('dev'));
} else {
    // 线上环境
    const logFileName = path.join(__dirname, 'logs', 'access.log')
    const writeStream = fs.createWriteStream(logFileName, {
        flags: 'a'
    })
    app.use(morgan('combined', {
        stream: writeStream
    }));
}

//session配置
app.keys = ['DSDSDsds890809'];
app.use(session({
    //配置cookie
    cookie: {
        path: '/',
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000
    },
    //配置redis
    store: redisStore({
        all: `${REDIS_CONF.host}:${REDIS_CONF.port}`
    })
}));

// routes
app.use(index.routes(), index.allowedMethods());
app.use(users.routes(), users.allowedMethods());
app.use(user.routes(), user.allowedMethods());
app.use(blog.routes(), blog.allowedMethods());

// error-handling
app.on('error', (err, ctx) => {
    console.error('server error', err, ctx)
});

module.exports = app

七、模拟中间件

const http = require('http');

//组合中间件
function compose(middlewareList) {
    return function (ctx) {
        //中间件调用
        function dispatch(i) {
            let fn = middlewareList[i]
            try {
                return Promise.resolve(fn(ctx, dispatch.bind(null, i + 1)))
            } catch (e) {
                return Promise.reject(e)
            }
        }

        return dispatch(0);
    }
}

class LikeKoa2 {
    constructor() {
        //中间件
        this.middlewareList = []
    }

    use(fn) {
        this.middlewareList.push(fn)
        return this
    }


    listen(...args) {
        let server = http.createServer(this.callback());
        server.listen(...args)
    }

    createCtx(req, res) {
        let ctx = {req, res};
        ctx.query = req.query;
        return ctx
    }

    handleRequest(ctx, fn) {
        return fn(ctx);
    }

    callback() {
        let fn = compose(this.middlewareList);
        return (req, res) => {
            let ctx = this.createCtx(req, res);
            return this.handleRequest(ctx, fn)
        };
    }
}

module.exports = () => {
    return new LikeKoa2();
}

测试:

const Koa = require('./likeKoa2');
const app = Koa();

// logger
app.use(async (ctx, next) => {
    await next();
    const rt = ctx['X-Response-Time'];
    console.log(`${ctx.req.method} ${ctx.req.url} - ${rt}`);
});

// x-response-time
app.use(async (ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    ctx['X-Response-Time'] = `${ms}ms`;
});

// response
app.use(async ctx => {
    ctx.res.end('This is like koa2');
});

app.listen(8000);

你可能感兴趣的:(后端,互联网技术,前端)