json-server + mock.js搭建先後端分離的mock服務

前言:

作前端的應該都知道作頁面的時候,當後端已經定義好了接口,但提供不了數據服務的時候,做爲前端的你搭建頁面是很痛苦的。 爲此搭建一個能夠mock數據的本地服務是頗有必要的。前端

用到的工具庫:json-server提供服務。mockjs提供模擬的數據。node

本文的目錄結構以下:webpack

1、實踐

一、安裝依賴web

npm install json-server mockjs --D
複製代碼

二、編寫db.json路由對應表npm

這是一個api路徑和路徑對應返回的內容組成的一個文件,好比:json

{
  "user_info": {
    "id": 1000,
    "course_name": "馬連白米且",
    "autor": "袁明",
    "college": "金並即總變史",
    "category_Id": 2
  }
}
複製代碼

上面的user_info就是你的api接口路徑,後面的value值就是這個接口返回的內容.後端

假如你本地起了一個json-server服務,http://localhost:6666,api

那麼你訪問http://localhost:6666/user_info獲得的就是如下內容:數組

{
  "id": 1000,
  "course_name": "馬連白米且",
  "autor": "袁明",
  "college": "金並即總變史",
  "category_Id": 2
}
複製代碼

但問題來了: 這樣簡單的定義一個db.json文件,你每次訪問http://localhost:6666/user_info的時候,獲得的都是同一份數據,它不會變。 這不是咱們想要的效果。咱們想要每次訪問都獲得不同的數據。bash

三、編寫每次都會變化的mock數據

mock/mockDB/test.js

// 引入mock.js
let Mock = require('mockjs');
let Random = Mock.Random;

// 編寫一個函數,這個函數利用mock.js動態生成mock數據
// 我看到不少教程這裏是直接輸出一個對象的,這樣每次訪問獲得的都是一樣的數據。不符合預期,
// 咱們這裏用函數包裝,每次訪問api的時候就執行一次該函數,獲得的就是新的mock數據了
function testList() {
  const monitorList = [];
  for (var i = 0; i < 3; i++) {
    monitorList.push(
      Mock.mock({
        userid: '25788869998_1562054852076593528',
        appid: Random.natural(100, 3000),
        content: Random.cparagraph(2, 4),
        timestamp: 1562054852,
      })
    );
  }
  
  // 這裏返回你想要的數據格式
  return {
    success: true,
    data: monitorList,
    message: '獲取數據成功',
  };
}

// 以api路徑爲值,將testList函數暴露出去
exports.user_info = testList;
複製代碼

四、編寫組裝db.json文件的代碼

如上文所說,json-server須要一個json文件作路由配置表,格式以下:

{
  "user_info": {
    "id": 1000,
    "course_name": "馬連白米且",
    "autor": "袁明",
    "college": "金並即總變史",
    "category_Id": 2
  }
}
複製代碼

很是注意的是: 路由配置裏,api路徑爲key值,返回的數據爲value值,這個value必須是數組或者對象。不能是函數,下面的寫法是會報錯的。

{
  "user_info": function () {
    return {
        "id": 1000,
        "course_name": "馬連白米且",
    }
  }
}
複製代碼

但想要每次請求同一個接口,返回的都是不同的數據,這個value必須是函數才行。這就是咱們在mock/mockDB/test.js定義的是函數的緣由。由於json-server的原理應該是:拿到訪問的路徑,而後經過路由配置表找到對應的value值,最後返回給用戶的。若是寫死成一個對象,或者數組,那麼每次訪問獲得的都是一樣的數據。

mock/db.js

將mockDB文件夾全部的mock數據文件讀取出來,組裝成上面路由配置表的格式,再暴露出去。 這裏能夠用webpack提供的require.context讀取全部文件,也能夠用node的fs模塊讀取全部文件。這裏我就不展開來寫了。簡單說一下流程。

// 引入mockDB文件夾下的文件,假若有如下文件
 let test1 = require('./mockDB/test.js');
 let test2 = require('./mockDB/test2.js');
 
 // 這裏定義一個收集的對象
let dbJson = {
  func: {},
  json: {},
}
// 收集mock函數,在server.js會用到
dbJson.func = {
  ...test1,
  ...test2,
};

// 獲取全部的api路徑
let apiPath = Object.keys(dbJson.func);

// 組裝json-server須要的路由表,這裏爲何都是空對象呢?
// 上面說過,路由表的value必須是對象或者數組。但咱們的mockDB文件夾下定義的都是mock函數,因此這裏要保證路由表是正確的,就要從新組裝一份符合格式的路由表。
apiPath.forEach(item => {
  dbJson.json[item] = {};
});

exports.dbJson = dbJson.json;
exports.dbFunc = dbJson.func;
複製代碼

五、搭建json-server本地服務

const jsonServer = require('json-server');
// 建立json-server實例
const server = jsonServer.create();
const jsonDB = require('./db');
// 將路由配置表傳入,生成路由表
const router = jsonServer.router(jsonDB.dbJson);
const middlewares = jsonServer.defaults();

// 這裏比較重要。
// 目的是:從新定義路由返回的數據。就是說:每訪問一個路由,返回response的時候,均可以通過router.render從新定義response數據
// 由於咱們在db.js裏將mock函數收集到了dbJson.func對象裏。
router.render = (req, res) => {
    // 根據請求的url,截取路徑。
    // 例如:通常狀況,res.url是/user_info?id=1234這樣的格式。
    let end = req.url.indexOf('?');
    let apiName = req.url.slice(1, end) || '';
    // 根據apiName拿到對應的mock函數,而後返回mock函數生產的mock數據
    // 由於每次返回response的時候,都會執行一次該函數,因此獲得的都是新的mock數據
    let response = dbJson.func[apiName] && dbJson.func[apiName]();
    res.send(response || {}));
};

server.use(middlewares);
// 導入路由
server.use(router);
// 在6666端口開服務
server.listen(6666, () => {
  console.log('JSON Server is running');
});
複製代碼

六、啓動服務

node mock/server.js
複製代碼

七、結束語

這篇文章是我的的實踐作法,若是有說的不對的地方,還望見諒、指正,謝謝

相關文章
相關標籤/搜索