Koa - 初體驗(寫個接口)


前言

  不會node.js的前端不是一個好前端!

  這幾年node.js確實是越來越火了,好多公司對node.js都開始有要求。雖說前端不一定要會后端,但想要成為一個優秀的前端,node.js是必經之路。

  我對於node.js的第一印象,認為它是一門后端語言,只是前端學習起來成本會更低更好上手。慢慢經過了解后,使用node.js寫接口對於前端來說很方便,但不僅限於寫接口。在一些大公司里,node.js並不是開發接口的首選目標,而是作為中間層來使用。我們都知道分工合作,讓專業的人做更專業的事,工作效率會大大提高。node.js作為中間層的存在,可以讓后端更專注於寫接口和管理數據。

  試想一下,現在由於業務邏輯改變,后端需要對數據接口進行更改,是否會花費時間?如果你會node.js,那么你就可以通過node.js來做數據聚合,從幾個接口中拼接數據供前端使用,而不需要為數據結構和數據內容煩惱,並且你不用擔心效率,因為node.js天生異步。

  包括我們常用的一些腳手架工具也是基於node.js環境搭建,你甚至還可以使用node.js來做數據挖掘,也就是我們所說的爬蟲,node.js的應用層面還有很多。以上都是我了解到的一些信息。

  目前node.js比較主流框架分為express、koa、egg。koa作為新一代的框架,由開發express的原班人馬打造,支持ES7 async/await,拋棄回調函數,在寫法上更自然。koa沒有綁定任何中間件,關鍵的設計點是在其低級中間件層中提供高級“語法糖”,koa的體積也因此更小。(中間件在koa中是一個很重要的存在,在后面我會着重去學習它)

  接下來,我要開始koa入坑之路。

 

koa初體驗

hello,koa!

安裝koa ,npm i koa

創建一個app.js,命令行執行 node app

const Koa = require('koa' ); const app = new Koa();  app.context.msg = 'Hello Koa!'  app.use(async ctx => { ctx.body = ctx.msg; });  app.listen( 3000);

app.context 為執行上下文添加屬性和方法  

app.use 將給定的中間件方法添加到應用程序中

該方法接收ctxnext作為參數,ctx 是執行上下文,里面存儲了request和response等信息,還有ctx.body,我們可以通過它來返回數據,next作為函數調用,將執行權交給下一個中間件執行。

這里我先安裝個nodemon,因為每次更改文件時,都需要重新執行命令以更新代碼,這種重復性的工作就交給模塊來處理。

通過 npm i nodemon 安裝好后,命令行執行 nodemon app,這樣每次更改文件時,nodemon都自動刷新。

 

Koa-router 路由管理

為了代碼的可維護性,減少代碼量。使用路由管理顯得尤為重要,koa框架也有自己對應的路由管理模塊(koa-router),我們可以通過npm 下載使用。

var Koa = require('koa' ); var Router = require('koa-router' ); var app = new Koa(); var router = new Router();  router.get( '/', (ctx, next) => { ctx.body = 'hello' }); 
//使用路由中間件 app .use(router.routes()) .use(router.allowedMethods()); app.listen(
3000 )

routes 注冊使用路由

allowedMethods 處理的業務是當所有路由中間件執行完成之后,若 ctx.status 為空或者404的時候,豐富 response 對象的 header 頭,不加問題也不大,官方例子有加上,所以我這里也加了

這時訪問3000端口就可以得到ctx.body 返回的內容

get請求

1. 獲取接口query參數

通過查詢 ctx.request.query 得到get參數, ctx.request.header 得到請求時的頭部信息,ctx.request.method 得到請求方法。這樣可以對應的來做一些判斷,例如請求的參數是否合法,請求方法是否合法。

router.get( '/get', (ctx, next) => { let id = ctx.request.query.id ctx.body = { id, code: 1 } });

 

2. 命名路由  獲取參數

router.get( '/get/:id', (ctx, next) => { let id = ctx.request.params.id ctx.body = { id, code: 1 } });

例如請求地址為 /get/123,通過 ctx.request.params 獲取參數

這寫法讓我想起了vue-router,設置params可以說是一樣了。

 

post請求

原生獲取post請求的參數,需要監聽ctx.req的data事件和end事件,分段拼接成完整的字符串,然后還需要切割轉碼。所以在獲取post參數時,我會借助 koa-bodyparser 來減少不必要的操作。

在引入 koa-bodyparser 時,需要注意的是順序問題,使用 koa-bodyparser 需要放在使用路由之前,這是由於中間件執行順序的原因(暫且理解為 bodyparser 經過處理,把處理好的值轉交到路由)

var bodyParser = require('koa-bodyparser'); app.use(bodyParser()); app .use(passport.initialize()) .use(passport.session())

 

借助中間件koa-bodyparser,訪問 ctx.request.body 得到post參數

通過 ctx.set 設置返回頭,設置多個時可傳入對象

router.post('/post', ctx=>{
   //設置允許跨域
   ctx.set('Access-Control-Allow-Origin','*') ctx.body
= { code:1, postParams:ctx.request.body } })

 

路由模塊化管理

試想一下,現在文件中寫有多個接口,我們在開發和調試起來都會特別麻煩,浪費時間。為了更好的管理接口,現在需要把接口按照功能抽離出來,封裝到一個個的JS文件中,並存放到routes文件夾下。

例如,創建 user.js 來存放用戶相關的接口

const Router = require('koa-router') const route = new Router() const jwt = require('jsonwebtoken') route.get('/getToken', async (ctx)=>{ let {name,id} = ctx.query if(!name && !id){ ctx.body = { msg:'不合法', code:0 } return } //生成token
    let token = jwt.sign({name,id},'secret',{ expiresIn: '1h' }) ctx.body = { token: token, code:1 } }) route.get('/getUser', async ctx=>{ let id = ctx.query.id ctx.body = { user:ctx.payload, id, code:1 } }) route.get('/getAllUser', async ctx=>{ let type = ctx.query.type if(type){ ctx.body = { type, code:1 } }else{ ctx.body = { msg:'缺少參數type', code:0 } } }) module.exports = route

以上代碼,將寫好的接口暴露出去,供app.js注冊使用

 

app.js代碼(部分代碼省略)

let urls = fs.readdirSync(__dirname + '/routes') urls.forEach((element) => { //routes里的js接口文件
    let module = require(__dirname + '/routes/' + element) //routes里的文件名作為 路由名
    router.use('/' + element.replace('.js', ''), module.routes()) }) //使用路由
app.use(router.routes()).use(router.allowedMethods()) app.listen(3000)

以上代碼,我大概講下流程

1. fs文件模塊讀取routes文件夾目錄內容(獲得的是一個文件名的數組)

2. 數組遍歷,引入接口文件,將文件名作為路由名,注冊使用路由

將 user.js 作為例子,user.js 內有一個 getUser 的接口,我訪問的api地址為 /user/getUser

 

頭部信息處理

在前后端交互中,頭部信息也是很關鍵的一步,通過對頭部信息的配置,可以對請求作出一些限制,或者是一些優化。

這里我會使用 koa2-cors 為例子,來對跨域做cors處理(部分代碼省略)。

const cors = require('koa2-cors') app.use(cors({ origin: function(ctx) { return 'http://127.0.0.1:5500';//cors
 }, exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'], maxAge: 5, credentials: true, allowMethods: ['GET', 'POST'], allowHeaders: ['Content-Type', 'Authorization', 'Accept'], })) app.use(router.routes()).use(router.allowedMethods()) app.listen(3000)

origin : 接受字符串和函數,這里配置的就是允許跨域的域名,如果允許所有域名跨域可傳入 *

allowMethods : 允許請求的方式

allowHeaders : 允許接受的頭部信息

其他的配置選項可以在npm上查看:https://www.npmjs.com/package/koa2-cors

 

寫在最后

本文通過路由中間件簡單實現接口,模塊化管理接口文件,還對接口進行跨域處理。

主要還是玩模塊,通過模塊可以組合出適合自己業務的系統。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM