koa

241 阅读4分钟

1、什么是koa?

\

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

koa洋葱模型,我们的ctx上下文是洋葱心,洋葱皮是我们的中间件机制。

2、搭建一个基础的koa服务

nodemon的简介:www.jianshu.com/p/f60e14db0…

npm init -y
npm install koa koa-router -S
/** nodemon是一种工具,可以自动检测到目录中的文件更改时通过重新启动应用程序来调试基于node.js的应用	* 程序。
	*/
npm install nodemon -D 

创建app.js

const Koa = require('koa');
const Router = require('koa-router');

//koa实例化
const app = new Koa();
const router = new Router();

router.get('/home',async ctx=>{
  ctx.body="hello World111";
})

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000,()=>{
  console.log('服务启动了')
})

package.json需要添加一条nodemon的命令,第8行

{
  "name": "koasimple",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "server":"nodemon app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "koa": "^2.13.1",
    "koa-router": "^10.0.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.12"
  }
}

基础koa服务的目录结构

3、拆分路由模块

  1. 创建一个routes的文件夹
  2. 创建一个user.js
const Koa = require('koa');
const Router = require('koa-router');

const user = require('./routes/user.js')

//koa实例化
const app = new Koa();
const router = new Router();
// 总路由添加前缀/api,总地址变为http://localhost:3000/api
router.prefix('/api')

router.get('/',async ctx=>{
  ctx.body="hello World111";
})


// 子路由添加前缀/users,最后访问地址变为http://localhost:3000/api/users/user
router.use('/users',user.routes());

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000,()=>{
  console.log('服务启动了')
})
const router = require('koa-router')();
 
router.get('/user', (ctx) => {
  ctx.body = {name:'tanwei'};
})
 
router.get('/userlist', (ctx) => {
  ctx.body = [{name:'tanwei'},{name:'weiwei'}]
})
 
module.exports = router;

4、拆分controllers

/controllers/user.js

class Users {
  async getUser(ctx){
    	ctx.body = {name:'tanwei'};
  }
  async getUserlist(ctx){
    	ctx.body = [{name:'tanwei'},{name:'weiwei'}];
  }
}

module.exports = new Users();

/routes/user.js

const router = require('koa-router')();
const { getUser,getUserlist } = require(''../controllers/user.js)
 
router.get('/user', (ctx) => {
  ctx.body = {name:'tanwei'};
})
 
router.get('/userlist', (ctx) => {
  ctx.body = [{name:'tanwei'},{name:'weiwei'}]
})
 
module.exports = router;

5、post请求如何处理

npm install koa-body -S

const koaBody = require('koa-body');

app.use(koaBody())


//通过ctx.request.body获取post参数

6、koa读写json文件

const fs = require('fs');
const path = require('path');
const router = require('koa-router')();


// 查询
router.get('/find', async (ctx) => {
  // 两种查询方式 1.id为空 => 查询全部  2.id有值 => 查询单个
      let id = ctx.request.query.id
      let findJson = () => {
          return new Promise((resolve,reject)=>{
              fs.readFile(path.join(__dirname, '../data/user.json'),function(err,data){
                  if(err){
                      resolve({code: -1, msg: '查询失败' + err})
                      return console.error(err);
                  }
                  let jsonData = data.toString();//将二进制的数据转换为字符串
                  jsonData = JSON.parse(jsonData);//将字符串转换为json对象
                  // 有id值=>单个 无id值=>全部
                  if (id) {
                    jsonData = jsonData.filter((item) => item.id === id);
                      // jsonData = jsonData.filter((item) => {return item.id === id});
                      resolve({code: 0, data: jsonData})
                  } else {
                      resolve({code: 0, data: jsonData})
                  }
   
              })
          })
      }
      ctx.body = await findJson()
  })

//新增和修改
router.post('/add-modify', async (ctx) => {
//  这里使用的body来解析post请求传来的数据,id是用来查找之前有的数据并进行修改,新增数据的在前台应该将id设置为空
    let id = ctx.request.body.id
    let params = ctx.request.body.params
    let writeJson = () => {
        return new Promise((resolve,reject)=>{
        // fs模块读取json文件  对fs、path模块不熟悉的可以去查下官方文档
            fs.readFile(path.join(__dirname, '../data/user.json'),function(err,data){
                if(err){
                // 报错返回
                    resolve({code: -1, msg: '新增失败' + err})
                    return console.error(err);
                }
                let jsonData = data.toString();//将二进制的数据转换为字符串
                jsonData = JSON.parse(jsonData);//将字符串转换为json对象
                // 有id值=>修改 无id值=>新增
                if (id) {
                    jsonData.splice(jsonData.findIndex(item => item.id === id), 1, params)
                } else {
                // 有重复 => 返回-1  无重复 => 将params加到json数组末尾
                    let hasRepeat = jsonData.filter((item) => item.id === params.id);
                    hasRepeat.length>0 ? resolve({code: -1, msg: '新增失败,有重复项目id'}) : jsonData.push(params);
                }
                //因为nodejs的写入文件只认识字符串或者二进制数,所以把json对象转换成字符串重新写入json文件中
                let str = JSON.stringify(jsonData,null,2);
                // let str = JSON.stringify(jsonData);
                fs.writeFile(path.join(__dirname, '../data/user.json'),str,function(err){
                    if(err){
                        resolve({code: -1, msg: '新增失败' + err})
                    }
                    resolve({code: 0, msg: '新增成功'})
                })
            })
        })
    }
    // 返回给前端
    ctx.body = await writeJson()
})

//删除
router.get('/delete', async (ctx) => {
  let id = ctx.request.query.id
  let deleteJson = () => {
      return new Promise((resolve,reject)=>{
          fs.readFile(path.join(__dirname, '../data/user.json'),function(err,data){
              if(err){
                  resolve({code: -1, msg: '删除失败' + err})
                  return console.error(err);
              }
              let jsonData = data.toString();//将二进制的数据转换为字符串
              jsonData = JSON.parse(jsonData);//将字符串转换为json对象
              // 过滤出所存item的id和前端传来id不等的 item ,下面提供了两种方法filter和splice
              jsonData = jsonData.filter((item) => item.id !== id);
              // jsonData.splice(jsonData.findIndex(item => item.id === id), 1)
              let str = JSON.stringify(jsonData,null,2);
              fs.writeFile(path.join(__dirname, '../data/user.json'),str,function(err){
                  if(err){
                      resolve({code: -1, msg: '删除失败' + err})
                  }
                  resolve({code: 0, msg: '删除成功'})
              })
          })
      })
  }
  ctx.body = await deleteJson()
})

module.exports = router;

7、koa连接mongodb数据库

//安装插件
npm install mongoose --save

在app.js这添加连接数据库的代码

const mongoose = require('mongoose');
// 连接数据库
mongoose.connect(connectionStr,(err)=>{
  if(err) console.log('mongonDB连接失败了');
  console.log('mongonDB连接成功了');
})

连接数据库的字符串抽取到了config.js文件里

module.exports = {
  connectionStr:'mongodb+srv://tanwei:19921010@cluster0.ooyzv.mongodb.net/myFirstDatabase?retryWrites=true&w=majority'
}

生成一个User模板,这个模板就是你定义的字段和字段的数据类型

首先我们分析一个用户会包含哪些属性

姓名、年龄、邮箱等等

用Schema生成model

/models/user.js

//models/user.js
const mongoose = require('mongoose');
const { Schema, model } = mongoose;

const userSchema = new Schema({
  name:{type:String,required:true},
  age:{type:Number,default:0}
})

module.exports = model('User', userSchema)

实现增删改的逻辑层

/controllers/users.js

const User = require('../models/user');

class UsersCtl {
  async find(ctx) {
    ctx.body = await User.find();
  }

  async findById(ctx) {
    const user = await User.findById(ctx.params.id);
    if(!user) {ctx.throw(404,'用户不存在')};
    ctx.body = user
  }

  async create(ctx) {
    const user = await new User(ctx.request.body).save();
    ctx.body = user;
  }

  async update(ctx) {
    const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body);
    const users = await User.findById(ctx.params.id);
    if (!users) { ctx.throw(404, '用户不存在'); }
    ctx.body = users;
  }
  async delete(ctx) {
    const user = await User.findByIdAndRemove(ctx.params.id);
    if (!user) { ctx.throw(404, '用户不存在'); }
    ctx.status = 204;
  }
}

module.exports = new UsersCtl();

子路由users.js

const Router = require('koa-router');
//const router = new Router({ prefix: '/users' });
const { find, findById, create,
  update, delete: del, } = require('../controllers/users');

router.get('/', find);
router.post('/', create);
router.get('/:id', findById);
router.patch('/:id', update);
router.delete('/:id', del);


module.exports = router;