• 有问题请联系QQ:2374146085
  • 有问题请联系QQ:2374146085

Node-Koa

2个月前 (12-04) 159次浏览 已收录 0个评论

Koa

导读

中间件、路由、参数解析、静态资源、错误处理、koa处理异步数据、express处理异步数据

创建服务器

const Koa = require('Koa')

const app = new Koa()

app.use((context,next)=>{
    // context.status=200
    // context.body="返回的内容" //有些可以直接使用某一个方法和属性,不需要response
    context.response.body="返回的内容"
})

app.listen(8000,()=>{
    console.log('启动成功')
})

中间件

koa注册中间件只能通过use方法

  • koa并没有提供methods的方式(get..)来注册中间件
  • 没有提供path中间件来匹配路径(‘/login’)
  • 也没有提供连续多个中间件的处理
  • 只能在路由的方式里才能实现多个中间件的使用

koa的中间件的调用和express之间不一样

  • 例如多个中间件中,express在匹配的所有中间件中,只要某一个中间件执行了res.send/res.json,那么后边匹配到的中间件就不会再执行了.
  • 而koa会对ctx.body先进行保存,等把所有通过next()匹配到的中间件执行完后,再返回body客户端数据.即洋葱模型
  • 而express只有在处理同步数据的时候才是洋葱模型

//koa没有提供这种方式
app.get('/',n,n2,(req,res)=>{
    res.send()
})

使用

const Koa = require('Koa')

const app = new Koa()

//use注册中间件
app.use((ctx,next)=>{
    if(ctx.request.url === '/login'){
        if(ctx.request.method === 'GET'){
            ctx.response.body = '登录成功'
        }
    }else{
        ctx.response.body = '先登录'
    }
})

app.listen(8000,()=>{
    console.log('启动成功')
})

路由

在koa中需要使用第三方库来实现路由.

用户路由文件users.js

const Router = require('koa-router') //第三方库

const router = new Router({prefix:"/users"})

// '/users'
router.get('/',(ctx,next)=>{
    ctx.response.body="用户信息"
})

// '/users/add'
router.get('/add',(ctx,next)=>{
    ctx.response.body="添加用户信息"
})

module.exports = router

koa可以在路由中使用多个中间件

router.get('/',n1,n2,(ctx,next)=>{
    ctx.response.body="返回的内容"
})

使用路由app.js

const Koa = require('koa')

const userRouter = require('./router/users')

const app = new Koa()

//use注册中间件
app.use((ctx,next)=>{
    next() //转交给下一个中间件
})

//注册路由
app.use(userRouter.routes())

//作用:自动实现遇到程序没有注册的请求方式后,会返回给后端该方式不允许(Method Not Allowed,code:405)
app.use(userRouter.allowedMethods())

app.listen(8000,()=>{
    console.log('启动成功')
})

allowedMethods()作用

自动实现遇到程序没有注册的请求方式后,会返回给后端该方式不允许(Method Not Allowed,code:405)

koa中的五种参数解析

我们通常通过query、params、json、x-www-form-urlencoded、form-body(包括它的文件上传)五种方式传递数据.

query和params的解析

const Koa = require('koa')

const Router = require('koa-router')

const userRouter = new Router({prefix:'/users'})

userRouter.get('/:id',(ctx,next)=>{
    console.log('query',ctx.request.query)
    console.log('params',ctx.request.params) //params必须配合路由使用,因为这样才知道哪些是路径,哪些是参数
})

const app = new Koa()

app.use(userRouter.routes())

app.listen(8000,()=>{
    console.log('启动成功')
})

// query [Object: null prototype] { name: 'wxl' }
// params { id: '100' }

json和x-www-form-urlencoded的解析

在koa里需要使用第三方库koa-bodyparser来解析这两种body,而且该库只要放在最前面,就可以同时解析这两种格式,不再需要指定了.

const Koa = require('koa')
const bodyParser = require('koa-bodyparser')

const app = new Koa()

app.use(bodyParser()) //要放在最前面,解析json和x-www-form-urlencoded

app.use((ctx,next)=>{
    console.log(ctx.request.body) //此时就可以拿到解析后的body数据了
    ctx.response.body="返回的内容"
})

app.listen(8000,()=>{
    console.log('启动成功')
})

//{ name: 'wxl' }
//{ name: 'zzl' }

form-body的解析

koa里需要第三方库koa-multer来解析

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

const userRouter = new Router({prefix:'/users'})

const upload = multer()

//只能在路由的方式里才能使用多个中间件的使用
userRouter.post('/add',upload.any(),(ctx,next)=>{
    console.log(ctx.req.body)
    ctx.response.body="返回的内容"
})

const app = new Koa()

app.use(userRouter.routes())

app.listen(8000,()=>{
    console.log('启动成功')
})

// [Object: null prototype] { name: 'wxl' }

文件上传

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

const uploadRouter = new Router({prefix:'/upload'})

const storage = multer.diskStorage({
    destination:(req,file,cb)=>{
        cb(null,'./imgs') //存储的位置
    },
    filename:(req,file,cb)=>{
        cb(null,Math.random()+'diy_name.png') //存储的文件名
    }
})
const upload = multer({
    // dest:'./imgs' 存储的位置(简单配置)
    storage:storage //复杂配置
})

//只能在路由的方式里才能使用多个中间件的使用
uploadRouter.post('/img',upload.single('file_key_name'),(ctx,next)=>{
    console.log(ctx.req.file)
    ctx.response.body="上传成功"
})

const app = new Koa()

app.use(uploadRouter.routes())

app.listen(8000,()=>{
    console.log('启动成功')
})

/*
{
  fieldname: 'file_key_name',
  originalname: '*O2022-11-29 20.17.29.png',
  encoding: '7bit',
  mimetype: 'image/png',
  destination: './imgs',
  filename: '0.2637499180920484diy_name.png',
  path: 'imgs/0.2637499180920484diy_name.png',
  size: 345631
}
*/

静态资源

koa需要第三方库koa-static来使用静态资源

const Koa = require('Koa')
const staticAssets = require('koa-static')

const app = new Koa()

app.use(staticAssets('./public'))

app.use((context,next)=>{

})

app.listen(8000,()=>{
    console.log('启动成功')
})

错误处理

koa的错误处理和express类似

const Koa = require('Koa')

const app = new Koa()

app.use((ctx,next)=>{
    const isLogin = false
    if(!isLogin){
        ctx.app.emit('myError',new Error('not_login'),ctx)
    }
})

app.on('myError',(err,ctx)=>{
    let status=''
    let message=''
    switch(err.message){
        case 'not_login':
            message="not login!"
            status=401
            break
        default:
            message="null"
            status=400
            break
    }
    ctx.status=status
    ctx.body=message
})

app.listen(8000,()=>{
    console.log('启动成功')
})

koa处理异步数据

对于express,它只能处理同步数据,对于一部分数据不太好处理,而koa是容易处理异步数据的,因为koa种的 next()返回的是一个promise,所以我们可以使用await来等待异步数据的结果,供下边代码使用.

比如说对于匹配的中间件里有异步操作时,我们需要在转交下一个中间件的时候使用await,这样才能保证能得到所有被处理过的结果.例如:

onst verifyUser = async (ctx, next) => {
  // 1.获取用户名和密码
  const { name, password } = ctx.request.body;

  // 2.判断用户名或者密码不能空
  if (!name || !password) {
    const error = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED);
    return ctx.app.emit('error', error, ctx);
  }

  // 3.判断这次注册的用户名是没有被注册过
  const result = await service.getUserByName(name);
  if (result.length) {
    const error = new Error(errorTypes.USER_ALREADY_EXISTS);
    return ctx.app.emit('error', error, ctx);
  }

  await next();
}

//因为第二个匹配的中间件是异步的
const handlePassword = async (ctx, next) => {
  const { password } = ctx.request.body;
  ctx.request.body.password = md5password(password)

  await next();
}

userRouter.post('/login',verifyUser,handlePassword)

 


渣渣龙, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Node-Koa
喜欢 (1)

您必须 登录 才能发表评论!