視頻地址:https://www.cctalk.com/v/15114923889408

文章
在前面幾節(jié)中,我們已經(jīng)實(shí)現(xiàn)了項(xiàng)目中的幾個(gè)常見(jiàn)操作:?jiǎn)?dòng)服務(wù)器、路由中間件、Get 和 Post 形式的請(qǐng)求處理等?,F(xiàn)在你已經(jīng)邁出了走向成功的第一步。
目前,整個(gè)示例中所有的代碼都寫在 app.js 中。然而在業(yè)務(wù)代碼持續(xù)增大,場(chǎng)景更加復(fù)雜的情況下,這種做法無(wú)論是對(duì)后期維護(hù)還是對(duì)患有強(qiáng)迫癥的同學(xué)來(lái)說(shuō)都不是好事。所以我們現(xiàn)在要做的就是:『分梨』。
分離 router
路由部分的代碼可以分離成一個(gè)獨(dú)立的文件,并根據(jù)個(gè)人喜好放置于項(xiàng)目根目錄下,或獨(dú)立放置于 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="請(qǐng)輸入用戶名:ikcamp"/>
<br/>
<input name="password" type="text" placeholder="請(qǐng)輸入密碼:123456"/>
<br/>
<button>GoGoGo</button>
</form>
`
})
// 增加響應(yīng)表單請(qǐng)求的路由
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 = '賬號(hào)信息錯(cuò)誤'
}
})
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')
})
代碼看起來(lái)清爽了很多。
然而到了這一步,還是不能夠高枕無(wú)憂。router 文件獨(dú)立出來(lái)以后,應(yīng)用的主文件 app.js 雖然暫時(shí)看起來(lái)比較清爽,但這是在只有一個(gè)路由,并且處理函數(shù)也非常簡(jiǎn)單的情況下。如果有多個(gè)路由,每個(gè)處理函數(shù)函數(shù)代碼量也都繁復(fù)可觀,這就不是主管們喜聞樂(lè)見(jiàn)的事情了。
接下來(lái)我們對(duì)結(jié)構(gòu)進(jìn)行進(jìn)一步優(yōu)化。
分離 controller 層
我們把路由對(duì)應(yīng)的業(yè)務(wù)邏輯也分離出來(lái)。
新增 controller/home.js
新建 controller 文件夾,增加一個(gè) home.js 文件,并從 router.js 中提取出業(yè)務(wù)邏輯代碼。
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="請(qǐng)輸入用戶名:ikcamp"/>
<br/>
<input name="password" type="text" placeholder="請(qǐng)輸入密碼: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 = '賬號(hào)信息錯(cuò)誤'
}
}
}
修改路由 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())
}
如此,將每個(gè)路由的處理邏輯分離到 controller 下的獨(dú)立文件當(dāng)中,便于后期維護(hù)。
目前的代碼結(jié)構(gòu)已經(jīng)比較清晰了,適用于以 node 作為中間層、中轉(zhuǎn)層的項(xiàng)目。如果想要把 node 作為真正的后端去操作數(shù)據(jù)庫(kù)等,建議再分出一層 service,用于處理數(shù)據(jù)層面的交互,比如調(diào)用 model 處理數(shù)據(jù)庫(kù),調(diào)用第三方接口等,而controller 里面只做一些簡(jiǎn)單的參數(shù)處理。
分離 service 層
這一層的分離,非必需,可以根據(jù)項(xiàng)目情況適當(dāng)增加,或者把所有的業(yè)務(wù)邏輯都放置于
controller當(dāng)中。
新建 service/home.js
新建 service 文件夾,并于該文件夾下新增一個(gè) home.js 文件,用于抽離 controller/home.js 中的部分代碼:
module.exports = {
register: async(name, pwd) => {
let data
if (name == 'ikcamp' && pwd == '123456') {
data = `Hello, ${name}!`
} else {
data = '賬號(hào)信息錯(cuò)誤'
}
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
}
}
重構(gòu)完成
下一節(jié)我們將引入視圖層 views,還會(huì)介紹使用第三方中間件來(lái)設(shè)置靜態(tài)資源目錄等。新增的部分前端資源代碼會(huì)讓我們的用例更加生動(dòng),盡情期待吧。
下一篇:視圖nunjucks——Koa 默認(rèn)支持的模板引擎


上一篇:iKcamp新課程推出啦~~~~~iKcamp|基于Koa2搭建Node.js實(shí)戰(zhàn)(含視頻)? HTTP請(qǐng)求