溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

KOA2中Restful方式路由的示例分析

發(fā)布時(shí)間:2021-08-03 09:16:45 來源:億速云 閱讀:111 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)KOA2中Restful方式路由的示例分析,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

API庫結(jié)構(gòu)

考慮到全部對(duì)象置于頂層將會(huì)造成對(duì)象名越來長,同時(shí)不便于維護(hù),故采取部分的分層結(jié)構(gòu)

如workflow模塊內(nèi)的prototypes,instances等等,分層的深度定義為層級(jí)

可訪問的對(duì)象集合(collection)的屬性滿足Restful設(shè)計(jì)

 -- workflow(category)
  -- prototypes(collection)
    -- [method] ...
    -- [method] ... 
  -- instances(collection)
 -- users(collection)
   --[method] List     #get :object/
   --[method] Instance   #get :object/:id
 -- ...
 -- ...

RESTFUL API 接口

將Restful API接口進(jìn)行標(biāo)準(zhǔn)化命名

.get('/', ctx=>{ctx.error('路徑匹配失敗')})        
.get('/:object', RestfulAPIMethods.List)
.get('/:object/:id', RestfulAPIMethods.Get)
.post('/:object', RestfulAPIMethods.Post)
.put('/:object/:id', RestfulAPIMethods.Replace)
.patch('/:object/:id', RestfulAPIMethods.Patch)
.delete('/:object/:id', RestfulAPIMethods.Delete)
.get('/:object/:id/:related', RestfulAPIMethods.Related)
.post('/:object/:id/:related', RestfulAPIMethods.AddRelated)
.delete('/:object/:id/:related/:relatedId', RestfulAPIMethods.DelRelated)

API對(duì)象

這個(gè)文件是來自微信小程序demo,覺得很方便就拿來用了,放于需要引用的根目錄,引用后直接獲得文件目錄結(jié)構(gòu)API對(duì)象

const _ = require('lodash')
const fs = require('fs')
const path = require('path')

/**
 * 映射 d 文件夾下的文件為模塊
 */
const mapDir = d => {
  const tree = {}

  // 獲得當(dāng)前文件夾下的所有的文件夾和文件
  const [dirs, files] = _(fs.readdirSync(d)).partition(p => fs.statSync(path.join(d, p)).isDirectory())

  // 映射文件夾
  dirs.forEach(dir => {
    tree[dir] = mapDir(path.join(d, dir))
  })

  // 映射文件
  files.forEach(file => {
    if (path.extname(file) === '.js') {
      tree[path.basename(file, '.js')] = require(path.join(d, file))
      tree[path.basename(file, '.js')].isCollection = true
    }
  })

  return tree
}



// 默認(rèn)導(dǎo)出當(dāng)前文件夾下的映射
module.exports = mapDir(path.join(__dirname))

koa-router分層路由的實(shí)現(xiàn)

創(chuàng)建多層路由及其傳遞關(guān)系

執(zhí)行順序?yàn)?/p>

 1 -- 路徑匹配
    -- 匹配到‘/'結(jié)束
    -- 匹配到對(duì)應(yīng)的RestfulAPI執(zhí)行并結(jié)束
    -- 繼續(xù)
 2 -- 傳遞中間件 Nest
 3 -- 下一級(jí)路由
 4 -- 循環(huán) to 1

const DefinedRouterDepth = 2
let routers = []
for (let i = 0; i < DefinedRouterDepth; i++) {
  let route = require('koa-router')()
  if (i == DefinedRouterDepth - 1) {
    // 嵌套路由中間件
    route.use(async (ctx, next) => {
      // 根據(jù)版本號(hào)選擇庫
      let apiVersion = ctx.headers['api-version']
      ctx.debug(`------- (API版本 [${apiVersion}]) --=-------`)
       if (!apiVersion) {
        ctx.error('版本號(hào)未標(biāo)記')
        return
      }
      let APIRoot = null
      try {
        APIRoot = require(`../restful/${apiVersion}`)
      } catch (e) {
        ctx.error ('API不存在,請(qǐng)檢查Header中的版本號(hào)')
        return
      }
      ctx.debug(APIRoot)
      ctx.apiRoot = APIRoot
      ctx.debug('---------------------------------------------')
      // for(let i=0;i<)
      await next()
    })
  }
  route
    .get('/', ctx=>{ctx.error('路徑匹配失敗')})
    .get('/:object', RestfulAPIMethods.List)
    .get('/:object/:id', RestfulAPIMethods.Get)
    .post('/:object', RestfulAPIMethods.Post)
    .put('/:object/:id', RestfulAPIMethods.Replace)
    .patch('/:object/:id', RestfulAPIMethods.Patch)
    .delete('/:object/:id', RestfulAPIMethods.Delete)
    .get('/:object/:id/:related', RestfulAPIMethods.Related)
    .post('/:object/:id/:related', RestfulAPIMethods.AddRelated)
    .delete('/:object/:id/:related/:relatedId', RestfulAPIMethods.DelRelated)


  if (i != 0) {
    route.use('/:object', Nest, routers[i - 1].routes())
  }
  routers.push(route)
}
let = router = routers[routers.length - 1]

Nest中間件

將ctx.apiObject設(shè)置為當(dāng)前層的API對(duì)象

const Nest= async (ctx, next) => {
  let object = ctx.params.object
  let apiObject = ctx.apiObject || ctx.apiRoot
  if(!apiObject){
    ctx.error('API裝載異常')
    return
  }

  if (apiObject[object]) {
    ctx.debug(`ctx.apiObject=>ctx.apiObject[object]`)
    ctx.debug(apiObject[object])
    ctx.debug(`------------------------------------`)
    ctx.apiObject = apiObject[object]
  } else {
    ctx.error(`API接口${object}不存在`)
    return
  }


  await next()
}

RestfulAPIMethods

let RestfulAPIMethods = {}
let Methods = ['List', 'Get', 'Post', 'Replace', 'Patch', 'Delete', 'Related', 'AddRelated', 'DelRelated']
for (let i = 0; i < Methods.length; i++) {
  let v = Methods[i]
  RestfulAPIMethods[v] = async function (ctx, next) {
    
    let apiObject = ctx.apiObject || ctx.apiRoot
    if (!apiObject) {
      ctx.error ('API裝載異常')
      return
    }
    let object = ctx.params.object
    if (apiObject[object] && apiObject[object].isCollection) {
      ctx.debug(` --- Restful API [${v}] 調(diào)用--- `)
      if (typeof apiObject[object][v] == 'function') {
        ctx.state.data = await apiObject[object][v](ctx)
        ctx.debug('路由結(jié)束')
        return
        //ctx.debug(ctx.state.data)
      } else {
        ctx.error(`對(duì)象${object}不存在操作${v}`)
        return
      }
    }
    ctx.debug(` --- 當(dāng)前對(duì)象${object}并不是可訪問對(duì)象 --- `)
    await next()
  }
}

需要注意的點(diǎn)

1、koa-router的調(diào)用順序
2、涉及到async注意next()需要加await

關(guān)于“KOA2中Restful方式路由的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI