iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 代码分层

视频地址:https://www.cctalk.com/v/15114923889408

文章

在前面几节中,我们已经实现了项目中的几个常见操作:启动服务器、路由中间件、GetPost 形式的请求处理等。现在你已经迈出了走向成功的第一步。

目前,整个示例中所有的代码都写在 app.js 中。然而在业务代码持续增大,场景更加复杂的情况下,这种做法无论是对后期维护还是对患有强迫症的同学来说都不是好事。所以我们现在要做的就是:『分梨』。

分离 router

路由部分的代码可以分离成一个独立的文件,并根据个人喜好放置于项目根目录下,或独立放置于 router 文件夹中。在这里,我们将它命名为 router.js并将之放置于根目录下。

修改路由 router.js

  const router = require('koa-router')()

  module.exports = (app) => {
    router.get('/', async(ctx, next) => {
      ctx.response.body = `<h1>index page</h1>`
    })
    
    router.get('/home', async(ctx, next) => {
      console.log(ctx.request.query)
      console.log(ctx.request.querystring)
      ctx.response.body = '<h1>HOME page</h1>'
    })
    
    router.get('/home/:id/:name', async(ctx, next)=>{
      console.log(ctx.params)
      ctx.response.body = '<h1>HOME page /:id/:name</h1>'
    })
    
    router.get('/user', async(ctx, next)=>{
      ctx.response.body = 
      `
        <form action="/user/register" method="post">
          <input name="name" type="text" placeholder="请输入用户名:ikcamp"/> 
          <br/>
          <input name="password" type="text" placeholder="请输入密码:123456"/>
          <br/> 
          <button>GoGoGo</button>
        </form>
      `
    })
    
    // 增加响应表单请求的路由
    router.post('/user/register',async(ctx, next)=>{
      let {name, password} = ctx.request.body
      if( name == 'ikcamp' && password == '123456' ){
        ctx.response.body = `Hello, ${name}!` 
      }else{
        ctx.response.body = '账号信息错误'
      }
    })
    
    app.use(router.routes())
      .use(router.allowedMethods())
  }

修改 app.js

  const Koa = require('koa')
  const bodyParser = require('koa-bodyparser')
  const app = new Koa()
  const router = require('./router')

  app.use(bodyParser())

  router(app)

  app.listen(3000, () => {
    console.log('server is running at http://localhost:3000')
  })

代码看起来清爽了很多。

然而到了这一步,还是不能够高枕无忧。router 文件独立出来以后,应用的主文件 app.js 虽然暂时看起来比较清爽,但这是在只有一个路由,并且处理函数也非常简单的情况下。如果有多个路由,每个处理函数函数代码量也都繁复可观,这就不是主管们喜闻乐见的事情了。

接下来我们对结构进行进一步优化。

分离 controller 层

我们把路由对应的业务逻辑也分离出来。

新增 controller/home.js

新建 controller 文件夹,增加一个 home.js 文件,并从 router.js 中提取出业务逻辑代码。

  module.exports = {
    index: async(ctx, next) => {
      ctx.response.body = `<h1>index page</h1>`
    },
    home: async(ctx, next) => {
      console.log(ctx.request.query)
      console.log(ctx.request.querystring)
      ctx.response.body = '<h1>HOME page</h1>'
    },
    homeParams: async(ctx, next) => {
      console.log(ctx.params)
      ctx.response.body = '<h1>HOME page /:id/:name</h1>'
    },
    login: async(ctx, next) => {
      ctx.response.body =
        `
        <form action="/user/register" method="post">
          <input name="name" type="text" placeholder="请输入用户名:ikcamp"/> 
          <br/>
          <input name="password" type="text" placeholder="请输入密码:123456"/>
          <br/> 
          <button>GoGoGo</button>
        </form>
      `
    },
    register: async(ctx, next) => {
      let {
        name,
        password
      } = ctx.request.body
      if (name == 'ikcamp' && password == '123456') {
        ctx.response.body = `Hello, ${name}!`
      } else {
        ctx.response.body = '账号信息错误'
      }
    }
  }

修改路由 router.js

修改 router.js 文件,在里面引入 controler/home

  const router = require('koa-router')()
  const HomeController = require('./controller/home')
  module.exports = (app) => {
    router.get( '/', HomeController.index )
    
    router.get('/home', HomeController.home)
    
    router.get('/home/:id/:name', HomeController.homeParams)
    
    router.get('/user', HomeController.login)
    
    router.post('/user/register', HomeController.register)
    
    app.use(router.routes())
      .use(router.allowedMethods())
  }

如此,将每个路由的处理逻辑分离到 controller 下的独立文件当中,便于后期维护。

目前的代码结构已经比较清晰了,适用于以 node 作为中间层、中转层的项目。如果想要把 node 作为真正的后端去操作数据库等,建议再分出一层 service,用于处理数据层面的交互,比如调用 model 处理数据库,调用第三方接口等,而controller 里面只做一些简单的参数处理。

分离 service 层

这一层的分离,非必需,可以根据项目情况适当增加,或者把所有的业务逻辑都放置于 controller 当中。

新建 service/home.js

新建 service 文件夹,并于该文件夹下新增一个 home.js 文件,用于抽离 controller/home.js 中的部分代码:

  module.exports = {
    register: async(name, pwd) => {
      let data 
      if (name == 'ikcamp' && pwd == '123456') {
        data = `Hello, ${name}!`
      } else {
        data = '账号信息错误'
      }
      return data
    }
  }

修改 controller/home.js

// 引入 service 文件
const HomeService = require('../service/home')
module.exports = {
  // ……省略上面代码
  // 重写 register 方法 
  register: async(ctx, next) => {
    let {
      name,
      password
    } = ctx.request.body
    let data = await HomeService.register(name, password)
    ctx.response.body = data
  }
}

重构完成

下一节我们将引入视图层 views,还会介绍使用第三方中间件来设置静态资源目录等。新增的部分前端资源代码会让我们的用例更加生动,尽情期待吧。

推荐: 翻译项目Master的自述:

1. 干货|人人都是翻译项目的Master

2. iKcamp出品微信小程序教学共5章16小节汇总(含视频)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端之路

web安全之XSS攻击

19030
来自专栏Young Dreamer

webpack的Hot Module Replacement运行机制

使用webpack打包,难免会使用Hot Module Replacement功能,该功能能够实现修改、添加或删除前端页面中的模块代码,而且是在页面不刷新的前提...

33050
来自专栏张善友的专栏

asp.net 性能调较

由于asp.net 处理进程在machine.config配置文件中的配置为<processModel autoConfig="true" />,这意味着你的a...

22570
来自专栏FreeBuf

如何使用Cron Jobs实现Linux提权

今天给各位渗透测试同行们提供一种Linux提权方法,在这篇文章中,我们将介绍如何使用Cron Jobs来实现Linux下的权限提升,并获取远程主机的root访问...

24700
来自专栏CaiRui

linux+Nginx+Mysql+Php

LNMP简介 LAMP(Linux apache mysql php)---比较早的web服务。 LNMP(Linux nginx mysql php)---比...

35490
来自专栏yl 成长笔记

消息队列的使用 RabbitMQ(一): 安装与总体介绍

RabbitMQ 是一款开源且比较流行的消息中间件。但用起来还是比较麻烦,有人封装了一层, 这就是 EasyNetQ 。

14020
来自专栏java架构师

Hadoop总结篇之四---底层通信是怎么做到的

上一篇介绍了一个job的提交过程。期间多次提到通信协议。那么协议是什么? 协议其实就是通信的双方所遵守的一套规范,这套规范规定了通信时传输的数据的固定的格式。 ...

37560
来自专栏架构师之路

线上操作与线上问题排查实战

技术同学需要经常登录线上的服务器进行操作,58到家架构部/运维部/58速运技术部,联合进行了一次线上操作与线上问题排查实战演练,同学们反馈有收获,特将实战演练的...

32840
来自专栏数据之美

关于 python ImportError: No module named 的问题

今天在 centos 下安装 python setup.py install 时报错:ImportError: No module named sysconfi...

61250
来自专栏FreeBuf

OpenStack:建立虚拟的渗透测试实验环境 – 网络篇

0x00 概述 对一个沙箱环境而言,其中最重要的一点就是网络的隔离,OpenStack网络支持Flat、VLAN、VXLAN等模式,配合路由器和防火墙可轻松虚拟...

39070

扫码关注云+社区

领取腾讯云代金券