专栏首页与前端沾边Koa入门(三)Koa 路由
原创

Koa入门(三)Koa 路由

Koa 应用中,通常会使用 koa-router 模块,提供对路由的支持。那为什么需要路由呢?做前后端分离开发的朋友都遇到过,对接接口的时候后台都会提供一个地址,请求这个地址,传相应参数就能实现相应地数据处理。你可以把这个接口理解为路由的地址

1 koa-router 使用

1.1 安装引入

  • npm i koa-router --save 新建 router.js 文件const Koa = require('koa') const Router = require('koa-router') const app = new Koa() const router = new Router() router.get('/', ctx => { ctx.body = '你好,测不准' }) // 注册路由 app.use(router.routes()) // 自动丰富 response 相应头,当未设置响应状态(status)的时候自动设置,在所有路由中间件最后设置(全局,推荐),也可以设置具体某一个路由(局部),例如:router.get('/index', router.allowedMethods()); 这相当于当访问 /index 时才设置 app.use(router.allowedMethods()) app.listen(3000, () => { console.log('监听3000端口') })增删改查的路由// 获取列表,返回数组 router.get('/', ctx => { ctx.body = [] }) // 根据id获取某一项,返回对象 router.get('/:id', ctx => { ctx.body = {} }) // 新建一项 router.post('/', ctx => { ctx.body = {} }) // 根据id更新某项 router.put('/:id', ctx => { ctx.body = {} }) // 根据id删除某一项 router.delete('/:id', ctx => { ctx.body = {} })koa-router(支持基础的常用的 http 方法('HEAD','OPTIONS','GET','PUT','PATCH','POST','DELETE'),生僻的请求方法会返回 501 状态码)
  • 如果如要在路由前增加逻辑判断,例如是否有权限访问,可以在路由中插入中间件// 定义中间件 const auth = async (ctx, next) => { if (ctx.url !== '/users') { ctx.throw(401) } await next() } // 注入 router.post('/users', auth, ctx => { ctx.body = ctx.request.body })

1.2 参数获取

  • get 获取参数 (ctx.params 或者 ctx.request.params)// 获取单个参数 router.get('/:id', ctx => { ctx.body = ctx.params }) // 获取多个参数 router.get('/:id/:age', ctx => { ctx.body = ctx.request.params })
  • post 获取参数(ctx.request.body) 获取参数需要用到第三方中间件,koa-bodyparsernpm i koa-bodyparser --saveconst Koa = require('koa') const Router = require('koa-router') const bodyParser = require('koa-bodyparser') const app = new Koa() const router = new Router() router.post('/', ctx => { ctx.body = ctx.request.body }) // 放到路由前面 app.use(bodyParser()) app.use(router.routes()) app.use(router.allowedMethods()) app.listen(3000, () => { console.log('监听3000端口') })

2 路由封装

我们开发项目不可能都把路由写在 index.js 入口文件中,需要使用单独的路由文件夹管理,只在入口文件引入一个即可。

  • 根目录创建 app/routes/home.jsconst Router = require('koa-router') const router = new Router() router.get('/', (ctx) => { ctx.body = '首页' }) module.exports = routerconst Router = require('koa-router') // **配置路由前缀** const router = new Router({ prefix: '/users' }) router.get('/', (ctx) => { ctx.body = '用户列表' }) router.get('/:id', ctx => { ctx.body = `用户id:${ctx.params.id}` }) module.exports = router因为一个项目中的路由的接口会有很多,不可能在入口 index.js 中每个都要引入,所以需要对所有路由做个处理,这样在入口文件中只要导入一个即可
  • 创建 app/routes/users.js
  • 创建 app/routers/index.jsconst fs = require('fs') module.exports = app => { // 读取当前目录下所有文件 fs.readdirSync(__dirname).forEach(file => { // 除去归纳的 `index.js` 文件,其他的都要注册到 `app` 中 if (file === 'index.js') return const router = require(`./${file}`) app.use(router.routes()).use(router.allowedMethods()) }) }... // 引入 const routing = require('./routes') ... // 使用 routing(app) ...
  • app/index.js 中引入

3 使用控制器

我们现在是把数据处理(虽然还没写数据,写死的哈)和路由放在一起,这样不便于维护处理,而且后面数据处理复杂了,会显得路由文件十分臃肿,我们应该把路由文件和数据处理分开来看。

  • 创建 app/controllers/home.jsclass HomeCtl { index(ctx) { ctx.body = '这是主页' } } module.exports = new HomeCtl()
  • 修改 app/routes/home.jsconst Router = require('koa-router') const router = new Router() // const { index } = require('../controllers/home') router.get('/', index) module.exports = router
  • 创建 app/controllers/users.jsclass UsersCtl { async find(ctx) { // 操作数据库一定要 await ctx.body = '用户列表' } async findById(ctx) { ctx.body = `用户id:${ctx.params.id}` } } module.exports = new UsersCtl

附:洋葱模型

通过前两节的介绍相信大家已经对 Koa 的执行机制有所了解,尤其是 await next() 执行完之后的中间件又会重新回来继续执行未执行的逻辑,不经感慨作者设计思路的巧妙。我们来简单了解下实现思路,核心代码在 koa-componse 中,代码也不多,我们简单学习下:

function compose(middleware) {
  return function(context) {
    // 我们其实只是返回了中间件的第一项,但是第一项执行过程中会递归执行后面的
    return dispatch(0);

    function dispatch(i) {
      let fn = middleware[i];
      try {
        // 每次执行 fn 函数时候,fn 中包含 next 函数(dispatch(i + 1)),所以有了先执行 next 代码,再回过头来执行该中间件下面的代码
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1));
      } catch (err) {
        return Promise.reject(err);
      }
    }
  };
}
  • 定义测试的中间件数组const middleware = [ async (ctx, next) => { console.log("1"); await next(); console.log("3"); }, async (ctx, next) => { console.log("2"); } ];我们可以看到,在中间件中执行 await next(),其实就是执行:await dispatch.bind(null, i + 1)。因此看起来,当前中间件会停止自己的逻辑,先处理下一个中间件。因为每个 dispatch,都返回新的 Promise。所以 async 会等到 Promise 状态改变后再回来继续执行自己的逻辑。
  • 简单写个按洋葱模型执行的方法(不考虑上线文,只是单纯的执行)let middlewares = [ async (next) => { console.log(1) await next() console.log(3) }, async (next) => { console.log(2) await next() }, async (next) => { console.log('test') } ] function componse() { return dispatch(0) async function dispatch(i) { let fn = middlewares[i] await fn(dispatch.bind(null, i + 1)) } } componse()

下一篇我们将学习数据库的操作,如果文章对你有帮助,欢迎关注呦!谢谢阅读!

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Koa配置路由

    明知山
  • 什么? 微信没有年度账单? 前端 nodejs 撸起来~ [接口实现]

    最近逛掘金看见一片文章 非官方统计 2018 微信年度账单实现,作者利用调试微信获取到了 2018 年的所有消费明细,并根据类型进行分类统计,作文一个前端,便萌...

    ihoey
  • 关于koa2,你不知道的事

    koa 是一个基于 node 实现的一个新的 web 框架,它是由 express 框架的原班人马打造。特点是优雅、简洁、表达力强、自由度高。和 express...

    lucifer210
  • 知新 | koa框架入门到熟练第一章

    是由Express原班人马打造,致力于成为一个更小的,更加富有表现力的,web框架。

    mySoul
  • Koa与常用中间件的使用

    Node.js 是一个异步的世界,官方 API 支持的都是 callback 形式的异步编程模型,这会带来许多问题,例如callback 的嵌套问题 ,以及异步...

    越陌度阡
  • Vue+koa2开发一款全栈小程序(4.Koa入门)

    玩蛇的胖纸
  • JavaScript 设计模式学习第二十九篇- 中间件

    (Middleware),又称中介层,是提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通,特别是应用软件对于系统软件的集中的逻辑。中间件在企业架...

    越陌度阡
  • koa使用koa-passport实现路由进入前登录验证

    现在的项目需求很简单,当进入一个页面的时候,如果没登录,则跳转到登录页面,如果登录了则直接到对应页面。

    蓓蕾心晴
  • Nuxt + Koa2 + Mongodb 手撸一个网上商城

    文档地址:https://finget.github.io/2019/08/06/nuxt-koa-mongodb/

    FinGet
  • Nuxt + Koa2 + Mongodb 手撸一个网上商城

    https://www.runoob.com/mongodb/mongodb-osx-install.html

    FinGet
  • 如何搭建 Koa 网站

    Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石...

    Mr.Crypto
  • Koa入门(二)搭建 Koa 程序

    安装 mkdir koa-demo && cd koa-demo && npm init -y && npm i koa --save && code .

    测不准
  • 从项目中由浅入深的学习koa 、mongodb(4)

    从项目中由浅入深的学习vue,微信小程序和快应用 (1) 从项目中由浅入深的学习react (2) 从项目中由浅入深的学习typescript (3)

    火狼1
  • Koa - 初体验(写个接口)

      这几年node.js确实是越来越火了,好多公司对node.js都开始有要求。虽说前端不一定要会后端,但想要成为一个优秀的前端,node.js是必经之路。

    WahFung
  • Node

    想要实现其他复杂的操作和效果,都要依靠 宿主环境 提供API,目前,已经嵌入 JavaScript 的宿主环境有多种,最常见的环境就是 浏览器 和 操作系统 ;

    jinghong
  • iKcamp|基于Koa2搭建Node.js实战(含视频)☞ HTTP请求

    原创作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校对:李益、大力萌、Au、DDU、小溪里、小哈 风采主播:可木、阿干、Au、DDU、小...

    iKcamp
  • node服务端渲染(完整demo)

    项目源码 git clone https://gitee.com/wjj0720/nod...

    random_wang
  • iKcamp|基于Koa2搭建Node.js实战(含视频)☞ HTTP请求

    POST/GET请求——常见请求方式处理 ?? iKcamp 制作团队 原创作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校对:李益、大力...

    iKcamp
  • iKcamp新书上市《Koa与Node.js开发实战》

    Node.js 10已经进入LTS时代!其应用场景已经从脚手架、辅助前端开发(如SSR、PWA等)扩展到API中间层、代理层及专业的后端开发。Node.js在企...

    iKcamp

扫码关注云+社区

领取腾讯云代金券