前言
Node.js也是寫了兩三年的時間了,剛開始學習Node的時候,hello world就是創建一個HttpServer,后來在工作中也是經歷過Express、Koa1.x、Koa2.x以及最近還在研究的結合著TypeScript的routing-controllers(驅動依然是Express與Koa)。
用的比較多的還是Koa版本,也是對它的洋蔥模型比較感興趣,所以最近抽出時間來閱讀其源碼,正好近期可能會對一個Express項目進行重構,將其重構為koa2.x版本的,所以,閱讀其源碼對于重構也是一種有效的幫助。
Koa是怎么來的
首先需要確定,Koa是什么。
任何一個框架的出現都是為了解決問題,而Koa則是為了更方便的構建http服務而出現的。
可以簡單的理解為一個HTTP服務的中間件框架。
使用http模塊創建http服務
相信大家在學習Node時,應該都寫過類似這樣的代碼:
const http = require('http')const serverHandler = (request, response) => {response.end('Hello World') // 返回數據}http.createServer(serverHandler).listen(8888, _ => console.log('Server run as http://127.0.0.1:8888'))一個最簡單的示例,腳本運行后訪問http://127.0.0.1:8888即可看到一個Hello World的字符串。
但是這僅僅是一個簡單的示例,因為我們不管訪問什么地址(甚至修改請求的Method),都總是會獲取到這個字符串:
> curl http://127.0.0.1:8888> curl http://127.0.0.1:8888/sub> curl -X POST http://127.0.0.1:8888
所以我們可能會在回調中添加邏輯,根據路徑、Method來返回給用戶對應的數據:
const serverHandler = (request, response) => {// defaultlet responseData = '404'if (request.url === '/') {if (request.method === 'GET') {responseData = 'Hello World'} else if (request.method === 'POST') {responseData = 'Hello World With POST'}} else if (request.url === '/sub') {responseData = 'sub page'}response.end(responseData) // 返回數據}類似Express的實現
但是這樣的寫法還會帶來另一個問題,如果是一個很大的項目,存在N多的接口。
如果都寫在這一個handler里邊去,未免太過難以維護。
示例只是簡單的針對一個變量進行賦值,但是真實的項目不會有這么簡單的邏輯存在的。
所以,我們針對handler進行一次抽象,讓我們能夠方便的管理路徑:
class App {constructor() {this.handlers = {}this.get = this.route.bind(this, 'GET')this.post = this.route.bind(this, 'POST')}route(method, path, handler) {let pathInfo = (this.handlers[path] = this.handlers[path] || {})// register handlerpathInfo[method] = handler}callback() {return (request, response) => {let { url: path, method } = requestthis.handlers[path] && this.handlers[path][method]? this.handlers[path][method](request, response): response.end('404')}}}
新聞熱點
疑難解答
圖片精選