首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端小白玩转koa(二)

前端小白玩转koa(二)

原创
作者头像
一起重学前端
修改2024-11-28 09:48:29
修改2024-11-28 09:48:29
3260
举报

“好事”文章推荐:《从零开始学习Python基础语法:打开编程大门的钥匙》

文章地址:https://cloud.tencent.com/developer/article/2471283

这篇文章介绍了 Python 基础语法,包括数据类型、控制流、函数等,并以待办事项管理器为例实践,有兴趣的朋友可以去了解下。

接上一篇

基于koa完成了全局错误处理、初始化(配置信息、自动生成api路由、全局错误码),接下来我们先写一个api试试水。

不写hello word了,就以微信公众号验证token为例

具体验证token可以看看我上上篇文章NestJS对接微信公众号(一)配置服务器验证 下面就写简单点

app/api/v1/wx.js

代码语言:js
复制
const Router = require('koa-router');

const router = new Router({
    prefix: '/v1/wx'
});

router.get('/', async (ctx, next) => {
    // TODO xxx
    ctx.body = 'hello, this is handle view';
})

module.exports = router;

api前缀是在nginx配置文件配置的,有兴趣可以看看我s9写的另一篇文章《前端学习部署node服务-腾讯云服务器宝塔模版》 在这里就不多讲解了

启动项目成功访问

成功访问

参数解析 && 静态资源

app.js

代码语言:js
复制
...
// 使用ctx.body解析中间件 ctx.request.body
app.use(bodyParser());
// 静态资源
app.use(static(path.join(__dirname, './static')))
...
获取参数

使用ctx.body解析中间件 ctx.request.body

ctx.request.body

ctx.request

book相关的接口

代码语言:js
复制
const Router = require('koa-router');

const { getValidateParams } = require('@middlewares/validateParams');
const { Auth } = require('@middlewares/auth');

const { addUserSchema } = require('@validator/user');
const { saveRecordSchema, getRecordSchema, delRecordSchema, dataListSchema } = require('@validator/book');

const { User } = require('@models/user');
const { Records } = require('@models/records');

const _ = require('lodash')

const router = new Router({
    prefix: '/v1/book'
});

router.post('/getRecords', new Auth().m, getValidateParams('POST', getRecordSchema), async (ctx, next) => {
    const records = await Records.getRecords(ctx.auth.uid, ctx.request.body.type);
    ctx.body = records
})

router.post('/saveData', new Auth().m, getValidateParams('POST', saveRecordSchema), async (ctx, next) => {
    const { id } = ctx.request.body
    if (id) {
        const record = await Records.findOne({ where: { id } })
        await record.update({ ...ctx.request.body })
        await record.save()
    } else {
        Records.create({ ...ctx.request.body });
    }
    throw new global.errs.Success();
})

router.post('/delData', new Auth().m, getValidateParams('POST', delRecordSchema), async (ctx, next) => {
    const { id, } = ctx.request.body
    const record = await Records.findOne({ where: { id } })
    await record.destroy();
    throw new global.errs.Success();
})


router.post('/getUserDataList', new Auth().m, getValidateParams('POST', dataListSchema), async (ctx, next) => {
    const MAX_LIMIT = 100;
    const { uid, openid, typeValue } = ctx.request.body
    let dataList = [];
    const records = await Records.findAll({ where: { uid, openid, typeValue } })
    if (records) {

        const total = records.length;
        const batchTimes = Math.ceil(total / 100);
        const tasks = [];
        for (let i = 0; i < batchTimes; i++) {
            const promise = Records.findAndCountAll({
                where: { uid, openid, typeValue }, offset: i,
                limit: MAX_LIMIT,
            })
            tasks.push(promise);
        }
    let res = await Promise.all(tasks);
    if (res.length > 0) {
            dataList = res.reduce((acc, cur) => {
                console.log(acc)
                console.log( cur)
                return ({
                    data: acc.rows.concat(cur.rows),
                    errMsg: acc.errMsg,
                })
            }).rows;
        }
    }

    ctx.body = {
        data: dataList,
        errCode: 0,
        errMsg: "操作成功",
    };
})

router.post('/register', getValidateParams('POST', addUserSchema), async (ctx, next) => {

    const user = {
        email: _.get(ctx.request, 'body.email'),
        password: _.get(ctx.request, 'body.repeat_password'),
        nickname: _.get(ctx.request, 'body.nickname')
    }

    User.create(user);

    throw new global.errs.Success();
})

module.exports = router;

接口参数校验joi

joi + github copilot 快速开发提升1000%效率

getValidateParams 参数校验中间件

返回参数错误提示信息

validateParams.js

代码语言:js
复制
/**
 * @description 参数校验中间件
 */

function getValidateParams(method, schema) {
    async function validateParams(ctx, next) {
        let data;
        if (method === 'GET') {
            // data = ctx.request.query;
            data = ctx.params;
        } else {
            data = ctx.request.body;
        }
        const { error } = schema.validate(data);
        if (error) {
            throw new global.errs.ParameterException(error.message)
        }
        await next();
    }
    return validateParams;
}

module.exports = { getValidateParams };
Joi validators

validators/book.js

代码语言:js
复制
const Joi = require('joi');

const idSchema = Joi.object({
    id: Joi.number().integer().required().messages({
        'number.base': 'id必须是数字',
        'number.integer': 'id必须是整数',
        'any.required': 'id是必须的'
    })
});
const pageSchema = Joi.object({
    page: Joi.number().integer().messages({
        'number.base': 'page必须是数字',
        'number.integer': 'page必须是整数',
    })
});
const addCommentSchema = Joi.object({
    id: Joi.number().integer().required().messages({
        'number.base': 'id必须是数字',
        'number.integer': 'id必须是整数',
        'any.required': 'id是必须的'
    }),
    content: Joi.string().required().max(12).messages({
        'string.base': 'content必须是字符串',
        'string.max': 'content最大长度为12',
        'any.required': 'content是必须的'
    })
});

const searchSchema = Joi.object({
    q: Joi.string().required().messages({
        'string.base': 'q必须是字符串',
        'any.required': 'q是必须的'
    }),
    start: Joi.number().integer().messages({
        'number.base': 'start必须是数字',
        'number.integer': 'start必须是整数',
    }),
    count: Joi.number().integer().messages({
        'number.base': 'count必须是数字',
        'number.integer': 'count必须是整数',
    }),
    summary: Joi.number().integer().messages({
        'number.base': 'summary必须是数字',
        'number.integer': 'summary必须是整数',
    })
});
const saveRecordSchema = Joi.object({
    bookName: Joi.string().required().messages({
        'string.base': 'bookName必须是字符串',
        'any.required': 'bookName是必须的'
    }),
    bookId: Joi.number().integer().required().messages({
        'number.base': 'bookId必须是数字',
        'number.integer': 'bookId必须是整数',
        'any.required': 'bookId是必须的'
    }),
    count: Joi.number().required().messages({
        'number.base': '金额必须是数字',
        'any.required': '金额是必须的',
        'number.max': '金额超过最大值',
    }),
    desc: Joi.string().required().messages({
        'string.base': 'desc必须是字符串',
        'any.required': 'desc是必须的'
    }),
    typeValue: Joi.number().integer().required().messages({
        'number.base': 'typeValue必须是数字',
        'number.integer': 'typeValue必须是整数',
        'any.required': 'typeValue是必须的'
    }),
    typeText: Joi.string().required().messages({
        'string.base': 'typeText必须是字符串',
        'any.required': 'typeText是必须的'
    }),
    incomeId: Joi.string().required().messages({
        'string.base': 'incomeId必须是字符串',
        'any.required': 'incomeId是必须的'
    }),
    incomeName: Joi.string().required().messages({
        'string.base': 'incomeName必须是字符串',
        'any.required': 'incomeName是必须的'
    }),
    uid: Joi.number().integer().required().messages({
        'number.base': 'uid必须是数字',
        'number.integer': 'uid必须是整数',
        'any.required': 'uid是必须的'
    }),
    openid: Joi.string().required().messages({
        'string.base': 'openid必须是字符串',
        'any.required': 'openid是必须的'
    }),
    date: Joi.date().required().messages({
        'date.base': 'date必须是日期',
        'any.required': 'date是必须的'
    }),
    id: Joi.number().integer().messages({
        'number.base': 'id必须是数字',
        'number.integer': 'id必须是整数',
    }),
});
const getRecordSchema = Joi.object({
    type: Joi.string().messages({
        'string.base': 'type必须是字符串',
    }),
    uid: Joi.number().integer().required().messages({
        'number.base': 'uid必须是数字',
        'number.integer': 'uid必须是整数',
        'any.required': 'uid是必须的'
    }),
});
const delRecordSchema = Joi.object({
    id: Joi.number().integer().required().messages({
        'number.base': 'id必须是数字',
        'number.integer': 'id必须是整数',
        'any.required': 'id是必须的'
    }),
});
const dataListSchema = Joi.object({
    typeValue: Joi.number().integer().required().messages({
        'number.base': 'typeValue必须是数字',
        'number.integer': 'typeValue必须是整数',
        'any.required': 'typeValue是必须的'
    }),
    uid: Joi.number().integer().required().messages({
        'number.base': 'uid必须是数字',
        'number.integer': 'uid必须是整数',
        'any.required': 'uid是必须的'
    }),
    openid: Joi.string().required().messages({
        'string.base': 'openid必须是字符串',
        'any.required': 'openid是必须的'
    }),
});
module.exports = {
    idSchema,
    pageSchema,
    addCommentSchema,
    searchSchema,
    saveRecordSchema,
    getRecordSchema,
    delRecordSchema,
    dataListSchema
}
应用

还是已book api为例

代码语言:js
复制
...
const { saveRecordSchema, getRecordSchema, delRecordSchema, dataListSchema } = require('@validator/book');

router.post('/getRecords', new Auth().m, getValidateParams('POST', getRecordSchema), async (ctx, next) => {
    const records = await Records.getRecords(ctx.auth.uid, ctx.request.body.type);
    ctx.body = records
})
...
体验一下copilot

不得不感叹代码助手确实在一定程度上提效

未完待续,koa开发持续更新中...

最后一篇讲讲微信小程序授权token&权限、jwt token 处理、sequelize 操作数据库、上传 koa-multer

感谢关注点赞评论~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接上一篇
    • 不写hello word了,就以微信公众号验证token为例
    • 参数解析 && 静态资源
      • 获取参数
    • 接口参数校验joi
      • getValidateParams 参数校验中间件
      • Joi validators
      • 应用
      • 体验一下copilot
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档