亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

node實現(xiàn)mock-plugin中間件的方法

 更新時間:2019年12月25日 09:13:22   作者:185的胖哥  
這篇文章主要介紹了node實現(xiàn)mock-plugin中間件的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

寫在前面

最近在使用Mockjs作為項目里面mock數(shù)據(jù)的工具,發(fā)現(xiàn)mockjs做的攔截部分是自己實現(xiàn)摸擬了一個XMLHttpRequest的方法做的攔截,使用Mockjs攔截請求后,在chromenetwork上無法看到請求(具體mockjs使用方法可以查看他的api,mockjs-api這里我不多做闡述),但為了更加真實的像后臺返回數(shù)據(jù),我自己使用Node作為中間代理去實現(xiàn)了一個mock-plugin.

express中間件介紹

因為插件相當(dāng)于是實現(xiàn)了一個express的中間件的方式,所以這里簡單對express中間件的使用做一個說明:

express中間件通過app.use(也有app.get,app.post等方法)的方式注冊到express的實例某個屬性上,將執(zhí)行函數(shù)存放在棧內(nèi)部,然后在回調(diào)執(zhí)行的時候調(diào)用next()方法將執(zhí)行下一個存在棧內(nèi)的方法。

這里列舉一個示例:

const express = require('express');
const app = express();

app.use(function (req, res, next) {
 console.log('first all use');
 next()
});

app.use(function (req, res, next){
 setTimeout(() => {
  console.log(`two all use`)
  next()
 }, 1000)
});

app.use(function (req, res, next) {
 console.log('end all use')
 next()
});

app.use('/', function (req, res, next) {
 res.end('hello use')
});

app.listen(4000, function () {
 console.log(`起動服務(wù)成功!`)
});

通過node執(zhí)行以上代碼后,在瀏覽器上通過訪問http://locahost:4000可以看到控制臺打?。?br />

可以發(fā)現(xiàn)在執(zhí)行的時候先執(zhí)行了use注冊的中間件,然后再執(zhí)行到get路由的時候,又執(zhí)行了app.use注冊的中間件。

詳細(xì)的express中間件可以在express官網(wǎng)查看

實現(xiàn)dev-server

devServer可以使用webpack-dev-server然后通過before的回調(diào)去做一層攔截,這樣也能夠?qū)崿F(xiàn)在響應(yīng)之前對后臺的數(shù)據(jù)做一些處理。

我這兒選擇自己實現(xiàn)一個devServer,在之前使用webpack-dev-server的服務(wù)大概需要配置,port, proxy,以及跨域https等。當(dāng)然自己實現(xiàn)devServer就沒必要實現(xiàn)那么多功能了,正常在開發(fā)場景下很多也不一定用得上,這里我主要使用了webpack-dev-middlewarewebpack-hot-middleware達(dá)到自動編譯和熱更新的目的,以及可以自己在中間添加express中間件.

貼上代碼:

onst path = require('path');
const express = require('express');
const webpack = require('webpack');
const webpackConfig = require('./webpack.dev');
const devMiddleware = require('webpack-dev-middleware');
const hotMiddleware = require('webpack-hot-middleware');
const app = express();
const compiler = webpack(webpackConfig); // webpack開發(fā)環(huán)境配置
const mockPlugin = require('./mock-plugin');

const config = {
 prd: 8800
};

 // 注冊webpack-dev-middleware中間件
app.use(
 devMiddleware(compiler, { 
  publicPath: webpackConfig.output.publicPath
 })
);

// 注冊webpack-hot-middleware中間件
app.use(
 hotMiddleware(compiler) 
);

// 注冊mockPlugin插件
app.use(
 mockPlugin({ 
  routes: {
   '/app': 'http://locahost:3002', // 測試代理到服務(wù)器的地址
   '/api': 'http://localhost:3003' // 測試代理到服務(wù)器的地址
  },
  root: path.resolve(__dirname) // 項目根目錄
 })
);

app.listen(config.prd, function () {
 console.log('訪問地址:', `http://localhost:${config.prd}`);
});

具體的一些演示操作,這里也不多講了(這不是實現(xiàn)mock-plugin的重點),網(wǎng)上也有很多如果通過webpack-dev-middlewarewebpack-hot-middleware的教程,唯一的區(qū)別是代理部分,網(wǎng)上可能用的是http-proxy之類已現(xiàn)有的工具,因為我們這兒需要在請求代理中間還需要處理一層,所以這兒我們自己實現(xiàn)mockPlugin注冊進(jìn)去。

摸擬mock文件

因為mock工具包含了一個請求后臺的結(jié)果自動寫入到Mock目錄下。所以這里將目錄層級設(shè)置為與請求路徑保持一致:

api接口:/app/home/baseInfo => 目錄:mock\app\home\baseInfo.js

對應(yīng) baseInfo.js 模板:

// mock 開關(guān)
exports.check = function () {
 return true;
}
// mock 數(shù)據(jù)
exports.mockData = function () {
 return {
  "success": true,
  "errorMsg": "",
  "data": {
   name: 'test'
  }
 }
}

當(dāng)checktrue時對就請求將會取mockData的數(shù)據(jù)。

主邏輯實現(xiàn)

mock-plugin主要暴露一個高階函數(shù),第一層為請求代理配置,返回的函數(shù)的參數(shù)與app.get('/')的回調(diào)參數(shù)一致,不描述細(xì)節(jié),大概輸出主要的邏輯。

// 獲取mock文件的mock數(shù)據(jù)
const setMockData = (moduleName) => {
 const {mockData} = require(moduleName);
 
 return mockData();
};

// 中間件暴露方法
module.exports = function (options) {
 const {routes, root} = options;

 return async (req, res, next) => {
  let {isReq, host} = await valid.isRequestPath(routes, req);

  // 不是請求地址直接return掉
  if (!isReq) {
   next();
   return;
  }

  // 如果存在Mock對應(yīng)的文件
  let filePath = await valid.isMockFileName(root, req.path);

  if (filePath) {
   // 檢驗本地mock文件開關(guān)是否開啟
   let check = await valid.inspectMockCheck(filePath);
   if (check) {
    // 發(fā)送本地mock數(shù)據(jù)
    return res.send(setMockData(filePath))
   } else {
    // 請求結(jié)果
    let body = await request(host, req, res).catch(proxyRes => {
     res.status(proxyRes.statusCode);
    });
    // 發(fā)送請求的結(jié)果信息
    return res.send(body);
   }
  } else {
   // 請求返回主體
   let body = await request(host, req, res).catch(proxyRes => {
    res.status(proxyRes.statusCode);
    next();
   });

   if (body) {
    // 定義需要寫入文件路徑
    const filePath = path.resolve(root, `mock${req.path}.js`);
    // 寫入mock文件
    writeMockFile(filePath, body);
    // 響應(yīng)返回主體
    return res.send(body);
   }
  }
 };
};

以下是一些校驗方法,詳細(xì)代碼就不貼了,具體源碼可查看:https://github.com/moxaIce/lo...

  • isRequestPath校驗是否為api接口請求, 返回 Promise包含isReq布爾值,host請求域名, route請求路由的對象
  • isMockFileName是否存在對應(yīng)的mock文件,返回Promise返回匹配路徑或者空字符串
  • inspectMockCheck校驗?zāi)M文件請求,開關(guān)是否開起, 返回布爾值

至于request方法和writeMockFile方法看下面的小結(jié)。

以下是我自己畫的一個邏輯圖,有點丑見諒:

請求代理

代理的作用不用多說,都知道是解決了前端起的服務(wù)和直接請求后臺的跨域問題。我這兒主要是在中間件內(nèi)部通過http.request方法發(fā)起一個http請求,對于http.request方法的使用可以看這里, 里面也有比較詳細(xì)的示例,我這兒貼上我寫的代碼:

/**
 * @description 請求方法
 */
const url = require('url');
const http = require('http');

module.exports = function (host, req, res) {
 let body = '';

 return new Promise((resolve, reject) => {
  const parse = url.parse(host);
  let proxy = http.request(
   {
    host: host.hostname,
    port: parse.port,
    method: req.method,
    path: req.path,
    headers: req.headers
   },
   (proxyRes) => {
    // 非200字段內(nèi)直接響應(yīng)錯誤 , 在主邏輯里處理
    if (proxyRes.statusCode < 200 || proxyRes.statusCode > 300) {
     reject(proxyRes)
    }

    proxyRes.on('data', (chunk) => {
     body += chunk.toString();
    }).on('end', () => {
     try {
      resolve(JSON.parse(body));
     } catch (e) {
      // 將響應(yīng)結(jié)果返回,在主文件做異?;卣{(diào)
      reject(proxyRes)
     }
    }).on('error', (err) => {
     console.log(`error is`, err);
    })
   });
  proxy.on('error', (e) => {
   console.error(`請求報錯:${e.message}`)
  });
  proxy.end()
 })
};

代理的實現(xiàn)比較簡單,主要通過外層傳入hostrequset, response在內(nèi)部用url解析得到ip然后配置requestoptions, 通過監(jiān)聽dataend事件將得到的主體報文resolve出去,以及中間對非200段內(nèi)的響應(yīng)處理。

文件寫入

通過中間傳options傳入的root, 可以得到完整的mock路徑path.resolve(__dirname, mock${req.path}.js)。傳入到寫入mock文件方法里

module.exports = async function (filePath, body) {
 await dirExists(path.dirname(filePath));

 fs.writeFile(filePath, echoTpl(JSON.stringify(body)), function (err) {
  if (err) {
   console.log(`寫入文件失敗`)
  }
 });
}

定義mockjs模板

module.exports = async function (filePath, body) {
 await dirExists(path.dirname(filePath));

 fs.writeFile(filePath, echoTpl(JSON.stringify(body)), function (err) {
  if (err) {
   console.log(`寫入文件失敗`)
  }
 });
}

dirExists通過遞歸的方式寫入文件目錄

module.exports = async function (filePath, body) {
 await dirExists(path.dirname(filePath));

 fs.writeFile(filePath, echoTpl(JSON.stringify(body)), function (err) {
  if (err) {
   console.log(`寫入文件失敗`)
  }
 });
}

效果演示

使用koa起一個node服務(wù)并且暴露如下路由和其中的數(shù)據(jù),具體代碼可以看這兒,我這兒只貼上了關(guān)鍵代碼

服務(wù)端代碼:

router.get('/app/home/baseInfo', user_controller.baseInfo)
router.post('/app/login', user_controller.login)

const login = async (ctx, next) => {
 ctx.body = {
  success: true,
  message: '',
  code: 0,
  data: {
   a: 1,
   b: '2'
  }
 }
};

const baseInfo = async (ctx, next) => {
 ctx.body = {
  success: true,
  errorMsg: '',
  data: {
   avatar: 'http://aqvatarius.com/themes/taurus/html/img/example/user/dmitry_b.jpg',
   total: 333,
   completed: 30,
   money: '500'
  }
 };
};

client代碼

mounted() {
  axios.get('/app/home/baseInfo', function (res) {
   console.log(`res 23`, res)
  });

  axios({
   url: '/app/login',
   method: 'post',
   headers: {
    // 'Content-Type': 'application/json;charset=UTF-8',
    'a': 'b'
   }
  })
 }

具體效果可以看下圖:


前端在訪問的時候會將后臺響應(yīng)的數(shù)據(jù)自動寫入到Mock目錄下。

結(jié)語

感覺在寫文章的過程中發(fā)現(xiàn)寫入mock文件的時候可能使用stream會更好一點,年底了業(yè)務(wù)需求不太多,避免上班劃水,隨便想了寫一寫~ 覺得有用的可以點個收藏+贊~

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • node.JS路徑解析之PATH模塊使用方法詳解

    node.JS路徑解析之PATH模塊使用方法詳解

    path模塊包含一系列處理和轉(zhuǎn)換文件路徑的工具集,通過 require('path') 可用來訪問這個模塊。本文將詳細(xì)介紹path模塊
    2020-02-02
  • NodeJs Express框架實現(xiàn)服務(wù)器接口詳解

    NodeJs Express框架實現(xiàn)服務(wù)器接口詳解

    最近學(xué)習(xí)了基于前后端分離的開發(fā)模式,我前端使用Vue框架,后端使用nodejs開發(fā)API接口,下面這篇文章主要給大家介紹了關(guān)于nodejs使用Express框架寫后端接口的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • node.js中的定時器nextTick()和setImmediate()區(qū)別分析

    node.js中的定時器nextTick()和setImmediate()區(qū)別分析

    本文介紹了node.js中的定時器nextTick()和setImmediate()的區(qū)別分析,非常的不錯,這里推薦給大家。
    2014-11-11
  • 使用nodejs+express實現(xiàn)簡單的文件上傳功能

    使用nodejs+express實現(xiàn)簡單的文件上傳功能

    這篇文章主要介紹了使用nodejs+express完成簡單的文件上傳功能,需要的朋友可以參考下
    2017-12-12
  • Node 切片拼接及地圖導(dǎo)出實例詳解

    Node 切片拼接及地圖導(dǎo)出實例詳解

    這篇文章主要為大家介紹了Node 切片拼接及地圖導(dǎo)出實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Node.js進(jìn)程管理之進(jìn)程集群詳解

    Node.js進(jìn)程管理之進(jìn)程集群詳解

    這篇文章介紹了Node.js進(jìn)程管理之進(jìn)程集群,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • sublime text配置node.js調(diào)試(圖文教程)

    sublime text配置node.js調(diào)試(圖文教程)

    下面小編就為大家分享一篇sublime text配置node.js調(diào)試(圖文教程),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • VsCode無法識別node問題解決過程

    VsCode無法識別node問題解決過程

    這篇文章主要給大家介紹了關(guān)于VsCode無法識別node問題解決的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2023-07-07
  • 深入淺出了解Node.js Streams

    深入淺出了解Node.js Streams

    這篇文章講了了解流的用途,為什么它們?nèi)绱酥匾?,以及如何使用它們。下面我們來一起學(xué)習(xí)吧
    2019-05-05
  • node基于async/await對mysql進(jìn)行封裝

    node基于async/await對mysql進(jìn)行封裝

    這篇文章主要介紹了node基于async/await對mysql進(jìn)行封裝,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下
    2019-06-06

最新評論