视频地址: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,还会介绍使用第三方中间件来设置静态资源目录等。新增的部分前端资源代码会让我们的用例更加生动,尽情期待吧。

下一篇:视图nunjucks——Koa 默认支持的模板引擎

上一篇:iKcamp新课程推出啦~~~~~iKcamp|基于Koa2搭建Node.js实战(含视频)☞ HTTP请求

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

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

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

iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 代码分层的更多相关文章

  1. iKcamp团队制作|基于Koa2搭建Node.js实战项目教学(含视频)☞ 环境准备

    安装搭建项目的开发环境 视频地址:https://www.cctalk.com/v/15114357764004 文章 Koa 起手 - 环境准备 由于 koa2 已经开始使用 async/await ...

  2. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 错误处理

    沪江CCtalk视频地址:https://www.cctalk.com/v/15114923887518 处理错误请求 爱能遮掩一切过错. 当我们在访问一个站点的时候,如果访问的地址不存在(404), ...

  3. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 记录日志

    沪江CCtalk视频地址:https://www.cctalk.com/v/15114923883523 log 日志中间件 最困难的事情就是认识自己. 在一个真实的项目中,开发只是整个投入的一小部分 ...

  4. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 解析JSON

    视频地址:https://www.cctalk.com/v/15114923886141 JSON 数据 我颠倒了整个世界,只为摆正你的倒影. 前面的文章中,我们已经完成了项目中常见的问题,比如 路由 ...

  5. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 处理静态资源

    视频地址:https://www.cctalk.com/v/15114923882788 处理静态资源 无非花开花落,静静. 指定静态资源目录 这里我们使用第三方中间件: koa-static 安装并 ...

  6. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 视图Nunjucks

    视频地址:https://www.cctalk.com/v/15114923888328 视图 Nunjucks 彩虹是上帝和人类立的约,上帝不会再用洪水灭人. 客户端和服务端之间相互通信,传递的数据 ...

  7. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 规范与部署

    沪江CCtalk视频地址:https://www.cctalk.com/v/15114923889450 规范与部署 懒人推动社会进步. 本篇中,我们会讲述三个知识点 定制书写规范 开发环境运行 如何 ...

  8. iKcamp团队制作|基于Koa2搭建Node.js实战(含视频)☞ 中间件用法

    中间件用法--讲解 Koa2 中间件的用法及如何开发中间件

  9. iKcamp团队制作|基于Koa2搭建Node.js实战(含视频)☞ 路由koa-router

    路由koa-router--MVC 中重要的环节:Url 处理器

随机推荐

  1. requestAnimationFrame 提高动画性能的原因

    与setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机.具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新 ...

  2. 自定义django的admin后台action

    django的admin后台管理系统中自带了一个批量删除所选对象的action. 我们还可以添加自定义的action来实现其它类似的功能,如批量修改某个字段的功能.简单的,例如将文章批量标记为已发布的 ...

  3. java编译需要文件后缀名.java 而运行不需要后缀名.class

    对于java源文件HelloWorld.java编译命令:javac HelloWorld.java运行命令:java HelloWorld 编译需要文件后缀名.java 而运行不需要后缀名.clas ...

  4. jquery编辑插件tinyMCE的使用方法

    jquery编辑插件tinyMCE是一个非常容易集成到您系统的一个html编辑插件,它不像FckEditor那样需要针对专门的后台语言集成,tinyMCE既能做到轻松集成asp.net,php,jav ...

  5. mysql 按照 where in 排序

    select * from user_extend where `unique` in('mark.liu@xxxx.com','jason.gan@xxxx.com','ssgao@xxxx.com ...

  6. shell 13文件包含

    同其他语言一样,shell也可以包含外部脚本.执行引用脚本可以使用source或 . 示例1 test.sh #shell #!/bin/sh echo "test.sh开始执行" ...

  7. [UE4]C++的const类成员函数

    我们知道,在C++中,若一个变量声明为const类型,则试图修改该变量的值的操作都被视编译错误.例如: const char blank = ‘’; blank = ‘\n’; // 错误 要声明一个 ...

  8. 【洛谷】P1341 无序字母对(欧拉回路)

    题目 传送门:QWQ 分析 快把欧拉回路忘光了. 欧拉回路大概就是一笔画的问题,可不可以一笔画完全图. 全图有欧拉回路当且仅当全图的奇数度数的点有0或2个. 2个时是一个点是起点,另一个是终点. 本题 ...

  9. nginx-1.8.1的安装

    1.我直接切换到root用户下安装,这里需要三个插件一起配套使用的 分别是: 1.gzip 模块需要 zlib 库 ( 下载: http://www.zlib.NET/ )2.rewrite 模块需要 ...

  10. 理解prototype

    从别人的博客里面盗了2张图,这2张图将对象/实例/prototype/__proto__/constructor之间的关系描绘的很清楚. 1.prototype 为 function的属性,实例化的对 ...