Koa

头像
小懵
    阅读 5 分钟

    Koa

    友情链接 https://jspang.com/detailed?i...

    1. npm init -y
    2. npm i koa2 --S
    3. package.json 配置启动脚本 "start": "node app.js"
    4. npm i nodemon -g "start": "nodemon app.js"
    5. 没有webpeck 翻译请不要使用import
    优点
    使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。一个Koa应用就是一个对象,包含了一个middleware数组,这个数组由一组Generator函数组成。这些函数负责对HTTP请求进行各种加工,比如生成缓存、指定代理、请求重定向等等。这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行。

    升级Node版本方法

    • Koa2的开发,Node.js是有要求的,它要求Node.js版本高于V7.6。因为node.js 7.6版本开始完全支持async/await,如果你的版本过低,还是windows系统,我告诉你一个最暴力的方法,直接下载新的安装包,重新安装,覆盖原来的安装位置。

      1 使用

      • 导入koa
      • 实例化app对象
      • 编写中间件 async
      • 将中间件添加至应用 app.use 返回this 也就是app本身
      • 启动服务启动监听
      • 使用postman 或者 浏览器访问
      // 一. 导入koa
      const Koa = require('koa')
      // 二. 实例化对象
      const app = new Koa()
      // 三. 编写中间件
      app.use((ctx) => {
      /*ctx context http 请求的上下文 ctx.body === ctx.response.body
        ctx.request:是Koa2中context经过封装的请求对象,它用起来更直观和简单。
      tx.req:是context提供的node.js原生HTTP请求对象。这个虽然不那么直观,但是可以得到更多的内容,适合我们深度编程。
      */
       ctx.body = 'hello Koa2'
      })
      // 四. 启动服务
      app.listen(3000, () => {
       console.log('server is running on http://localhost:3000')
      })
      注意

      如果没有通过ctx.body返回给客户端, 最终会得到Not Found

    2 洋葱模型

    与express 不同 express是所有中间件顺序执行结束后响应.koa遇见next后会跳出当前中间件,执行下一个中间件,直到没有next 然后回到上一个中间件执行next之后的代码,直到第一个。所以在use中, 一次只能接受一个函数做为参数

      app.use(async (ctx, next)=> {
        console.log(1);
        ctx.body='222';
        await next();
        // 想输出1 必须等待上面的next结束 记得画图
        console.log(1);
      })
      .use(async (ctx, next)=> {
        console.log(2);
        await next()
        console.log(2);
      })
      .use(async (ctx, next)=> {
        console.log(3);
        await next()
        console.log(3); 
      })
    //输出 1 2 3 2 1

    2.1 异步处理

    如果中间件中存在一些异步的代码, Koa也提供了统一的处理方式. 首先, 我们要了解async await语法

    1) async await语法

    async: 声明异步函数

    await: 后跟一个promise对象

    如果要使用await, 需要在函数声明前加上async

    2) 示例

    需求
    1. 在middleware1中, 构造一个message = aa
    2. 在middleware2中, 同步追加bb
    3. 在middleware3中, 异步追加cc

    最终在middleware1中, 通过body返回数据

    2.2 中间件

    顾名思义, 中间件就是在什么的中间

    在请求和响应中间的处理程序

    有时候从请求到响应的业务比较复杂, 将这些复杂的业务拆开成一个个功能独立的函数, 就是中间件

    对于处理请求来说,在响应发出之前,可以在请求和响应之间做一些操作,并且可以将这个处理结果传递给下一个函数继续处理

    中间件函数,帮助拆解主程序的业务逻辑,
    并且每一个的中间件函数处理的结果都会传递给下一个中间件函数。
    就好比工厂里流水线工人清洗一个箱子:
    第一个人清洗侧面,第二个人清洗底面,第三个人清洗顶面,。。。
    这条流水线结束后,箱子也就清洗干净了
    各做各的,不相互影响,又彼此协作

    image-20211208184728196

    3. 路由

    1 什么是路由

    路由
    • 建立URL和处理函数(中间件)之间的对应关系
    • 主要作用: 根据不同的Method和URL返回不同的内容
    需求

    根据不同的Method+URL, 返回不同的内容
    要求:

    • Get 请求/, 返回'这是主页'
    • Get 请求/users, 返回'这是用户页'
    • Post请求/users, 返回'创建用户'
      原生实现

        //     一. 导入koa
        const Koa = require('koa')
        // 二. 实例化对象
        const app = new Koa()
        // 三. 编写中间件
        app.use((ctx) => {
          if (ctx.url == '/') {
            ctx.body = '这是主页'
          } else if (ctx.url == '/users') {
            if (ctx.method == 'GET') {
              ctx.body = '这是用户列表页'
            } else if (ctx.method == 'POST') {
              ctx.body = '创建用户'
            } else {
              ctx.status = 405 // 不支持的请求方法
            }
          } else {
            ctx.status = 404
          }
        })
        // 四. 启动服务
        app.listen(3000, () => {
          console.log('server is running on http://localhost:3000')
        })

      原生书写代码的可维护性差,业务复杂,原生也不够友好。由此出现路由中间件

    路由中间件 npm i koa-router

    提供了405 501状态 router.allowedMethods通过它来实现
    4** 客户端错误 请求方式不支持
    5** 服务器错误 服务器没有这种请求方式
    在koa的基础上

    1. 导入`koa-router`包
    2. 实例化router对象
    3. 使用router处理路由
    4. 注册中间件
    
    // app 入口文件
    const Koa = require('koa2');
    const Router = require('koa-router');
    // 声明应用
    const app = new Koa();
    const router = new Router();
    
    router.get('/', async ctx => {
       ctx.body = 'router'
    })
    // 注册中间件 router.routes()启动路由  router.allowedMethods()允许任意请求
    app.use(router.routes(), router.allowedMethods())
      .listen (9000,()=>{
         console.log('serve start.....111');
     })
    路由重定向

    路由入口文件中书写

    router.redirect('/', '/home') 参数1 用户输入的 参数2是重定向的
    路由前缀

    比如在user.route.js中
    定义路由对象时传入参数

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

    对于router.get('/') == > 实际就是/users

    子路由

    路由入口文件中书写

    router.use ('/list', 第一层子路由list.routes(),list.allowedMethods())
    404无效路由
    错误处理
    项目拆解

    app.js 是入口文件,里面不要写路由的东西。创建一个路由文件夹,但是路由文件也需要拆分,index.js是路由的入口,只做重定向,其他的路由定义不同的js文件

    4 参数解析

    1 为什么

    在很多场景中, 后端都需要解析请求的参数, 作为数据库操作的条件。

    场景一

    前端希望通过请求, 获取id=1的用户信息

    image-20211009154415445

    接口设计

    GET /users/:id
    解决

    在GET请求中, 有些参数可以通过路由传参, 可以通过params得到

    // GET /users/:id ---- 根据id获取单个用户的信息, 返回一个对象
    router.get('/:id', (ctx) => {
      // 解析id参数
      const id = ctx.params.id
      const res = db.filter((item) => item.id == id)
    
      if (!res[0]) ctx.throw(404)
    
      ctx.body = res[0]
    })
    场景二

    前端希望查询年龄在18到20的用户信息

    image-20211009161051380

    解决

    在GET请求中, 如果以键值对的形式传参, 可以通过query得到

    // GET /users?start=18&end=20 ---- 获取所有的用户信息, 返回一个数组
    router.get('/', (ctx) => {
      // 通过 ctx.query 是ctx.request.query的代理 解析键值对参数
      const { start = 0, end = 0 } = ctx.query
      const res = db.filter((item) => item.age >= start && item.age <= end)
      // 解析键值对
      res.length == 0 ? ctx.throw(404) : (ctx.body = res)
    })
    场景三

    前端注册, 填写了用户名, 年龄, 传递给后端, 后端需要解析这些数据, 保存到数据库

    image-20211009161448091

    接口设计

    解决

    Koa不支持body参数解析, 通常借助社区的中间件实现. 官方推荐的有

    • koa-bodyparser
    • koa-body

    1) 安装koa-body

    npm install koa-body

    2) 注册

    // 注册KoaBody中间件, 解析请求体中的参数, 挂载到ctx.request.body
        const KoaBody = require('koa-body')
        app.use(KoaBody())

    3) 使用

    通过ctx.request.body获取请求体中的数据

    小结

    对于不同的Http请求, 需要使用不同的方式携带参数

    • GET请求: 在URL中以键值对传递
    • POST/PUT/PATCH/DELET请求: 在请求体中传递

    五. 错误处理

    对于接口编程, 错误处理是非常重要的环节, 通过提供更友好的提示

    1. 提高错误定位的效率
    2. 提高代码的稳定性和可靠性

    1 原生的错误处理

    一般Koa中的错误分为三类

    • 404: 当请求的资源找不到, 或者没有通过ctx.body返回时, 由koa自动返回
    • 手动抛出: 通过ctx.throw手动抛出
    • 500: 运行时错误

    Koa类是继承Emitter类, 因此可以

    • 通过emit提交一个错误
    • 通过on进行统一错误处理
    app.on('error', (err, ctx) => {
      console.error(err)
      ctx.body = err
    })
    只能捕捉ctx.app.emit的错误

    2 使用中间件

    1) 安装

    npm i koa-json-error

    2) 使用

    基本使用
    const error = require('koa-json-error')
    app.use(error())
    高级使用
    const error = require('koa-json-error')
    app.use(
      error({
        format: (err) => {
          return { code: err.status, message: err.message, result: err.stack }
        },
        postFormat: (err, obj) => {
          const { result, ...rest } = obj
          return process.env.NODE_ENV == 'production' ? rest : obj
        },
      })
    )

    vscode 调试node 代码

    node Launch Program


    小懵
    4 声望0 粉丝

    « 上一篇
    redux
    下一篇 »
    node