koa2 資料api中介軟體設計模型的實現方法
阿新 • • 發佈:2020-07-14
假設所有的資料庫讀取,http api 介面請求都為一箇中間件,將中介軟體當做外掛,插入需要獲取資料的位置。
api.js
module.exports = async (ctx,next) => { ctx.share_data.api_data = await axios.get('/api'); await next(); };
db.js
module.exports = async (ctx,next) => { ctx.share_data.db_data = await mysql_query('SELECT XXX').catch(() => {}); await next(); };
串聯
app.js
const api = require('api.js'); const db = require('db.js'); app.get('/get-api',api,(ctx) => ctx.body = ctx.share_data); app.get('/get-db',db,(ctx) => ctx.body = ctx.share_data); app.get('/get-api-and-db',(ctx) => ctx.body = ctx.share_data);
看著挺和諧,但是如果有多個數據中介軟體串聯則會導致介面的響應時間為所有中介軟體的總和。
併發
可義一個 compose 函式,需要併發的中介軟體包裝起來
super-compose.js
module.exports = (middleware = []) => { if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!'); for (const fn of middleware) { if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!'); } return async (context = {},next = f => f) => { await Promise.all( middleware.map(middleware => { return new Promise((rs,rj) => { middleware(context,() => Promise.resolve()) .then(rs) .catch(rj); }); }),); await next(); }; };
app.js
const api = require('api.js'); const db = require('db.js'); const superCompose = require('super-compose.js'); app.get('/get-api-and-db',superCompose([api,db]),(ctx) => ctx.body = ctx.share_data);
依賴關係
看著貌似解決了,但如何處理具有上下文依賴的情況呢?例如 api_1 依賴 api 的資料。
改下 api.js,加上快取校驗。處理可能被多次compose的重複介面呼叫
module.exports = async (ctx,next) => { if (ctx.share_data.api_data) { return await next(); } ctx.share_data.api_data = await axios.get('/api'); await next(); };
api-1.js
const api = require('api.js'); module.exports = compose([ api,async (ctx,next) => { const { api_data: { api_data: { id = 0 } = {} } = {} } = ctx; if (id < 0) { await next(); } else { ctx.api_data.api_1_data = await axios.get('/api',{ params: { id } }); } await next(); },])
app.js
const api_1 = require('api_1.js'); const db = require('db.js'); const superCompose = require('super-compose.js'); app.get('/get-api-and-db',superCompose([api_1,(ctx) => ctx.body = ctx.share_data);
跳過中介軟體
有時候,需要根據特定的條件,繞過某些介面呼叫
改造下 api.js,通過加入過濾列表
module.exports = async (ctx,next) => { const { break_list = [] } = ctx; if (break_list.includes('api_data')) { // 可能會誤傷其他組合引用該中介軟體的情況。 // 如可能會誤傷,可加上。 // ctx.break_list = break_list.filter(v => v !== 'api_data') return await next(); } else { ctx.share_data.api_data = await axios.get('/api'); } await next(); }
app.js
const api = require('api.js'); const db = require('db.js'); const superCompose = require('super-compose.js'); app.get( '/get-api-and-db',next) => { ctx.break_list = ['api_data']; await next(); },ctx => (ctx.body = ctx.share_data) );
資料合併處理
結合 super-compose 與 koa-compose 將所有需要的中介軟體組合起來,在寫一個針對頁面的controller
const api = require('api.js'); const db = require('db.js'); const superCompose = require('super-compose.js'); const compost = rquire('koa-compose') const babala = compose([ superCompose([api,next) => { const { share_data: { api_data: { id = 0 } = {},db_data: { title } = {} } = {},} = ctx; ctx.body = { id,title }; // OR // ctx.share_data.babala = {} },]); app.get( '/get-api-and-db',babala );
結尾
解決經常出現的一個函式內大量的介面、邏輯操作,超長的上下文邏輯。
app.get('/api',async ctx => { const api_1 = await axios.get('/api_1'); await api_2 = await axios.get('/api_2'); // ... // ... // 這裡有一百行 // ... const [api_3,api_4] = await new Promise.all([axios.get('/api_3'),axios.get('/api_4')]); // ... // ... // 這裡有幾百行 // ... ctx.body = {}; });
以上就是koa2 資料api中介軟體設計模型的實現方法的詳細內容,更多關於koa2 中介軟體設計模型的資料請關注我們其它相關文章!