1. 程式人生 >前端設計 >Mock資料從未如此簡單

Mock資料從未如此簡單


前後端分離的專案中,前端往往需要自己構造假資料進行渲染。作為一名合格且優秀的前端開發人員當然是希望一次性編碼,後面前後端聯調的時候最好什麼都不用做,直接一個文件丟給後端自己就可以愉快的進行下一個專案了。為了寫程式碼能夠一瀉千里,我們一般在編寫程式碼之前做一個簡單的資料格式文件定義,然後前後端就可以開始自己做自己的任務了。

前端渲染頁面往往需要假資料,假資料如果放在邏輯程式碼中去構造或者在 api 管理介面中統一返回假資料都會導致後期需要修改程式碼,最終會導致工作量增加無心談戀愛。所以我們前端最好的 mock 資料方式就是寫一個 node 服務,模擬真實的互動環境。

目標

使用 node 編寫一個微服務,允許各種請求方式,並返回相應的資料。

依賴

node、koa、koa-router、koa-logger、koa-cors、nodemon

我希望:

  1. 能夠模擬各種場景,允許跨域、允許 POST、GET、DELETE、PUT、PATCH 請求
  2. 只關心資料
  3. 熱響應

思路

  1. 實現自動遍歷目錄下的 json 檔案,作為資料返回
  2. 根據檔案字尾 .get.json、.post.json 等自動響應各種請求
  3. 使用 nodemon 啟動服務實現熱響應
  4. 程式碼寫好後,以後只關心 json 資料檔案
  5. 隨機返回成功和失敗(小概率失敗,大概率成功。暫時未實現,留給你們自己)

目錄結構大致如下:

目錄結構

請求方式:

// 模擬使用者登入
http://127..0.0.1:8080/api/v1/user/login

// 模擬從遠端獲取訊息記錄
http://127..0.0.1:8080/api/v1/message/remote/list
複製程式碼

程式碼

const Koa = require('koa')
const KoaRouter = require('koa-router')
const KoaLogger = require('koa-logger')

const cors = require('@koa/cors')
const { resolve } = require('path')
const fs = require('fs')

const app = new Koa()
const router = new KoaRouter({ prefix: '/api' })

glob.sync(resolve('./api',"**/*.json")).forEach(item => {
    let apiJsonPath = item && item.split('/api')[1];

    // inspect koa-router allowedMethods
    let method = apiJsonPath.endsWith('.get.json')
                    ? 'GET' : apiJsonPath.endsWith('.post.json')
                    ? 'POST' : apiJsonPath.endsWith('.patch.json')
                    ? 'PATCH' : apiJsonPath.endsWith('.put.json')
                    ? 'PUT' : apiJsonPath.endsWith('.delete.json')
                    ? 'DEL' : 'ALL'
    let apiPath = apiJsonPath
                    .replace('.get.json','')
                    .replace('.post.json','')
                    .replace('.put.json','')
                    .replace('.delete.json','');

    if (method === 'ALL') {
        ctx.body = 'OK'
        return
    }

    router[method.toLowerCase()](apiPath,ctx => {
        try {
            let jsonStr = fs.readFileSync(item).toString();
            ctx.body = {
                data: JSON.parse(jsonStr),code: 200,msg: 'OK',success: true
            }
        } catch(err) {
            ctx.throw('伺服器錯誤',500);
        }
    });
});

app
    .use(cors({
        origin: ctx => {
            const whiteList = ['http://localhost:8080','http://localhost:8081']
            let url = ctx.header.referer.substr(0,ctx.header.referer.length - 1) // remove '/'
            if(whiteList.includes(url)){
                return url
            }
            return "http://localhost:3000"
        },maxAge: 3,// https://zhuanlan.zhihu.com/p/86953757
        credentials: true,// is allowed cookie
        allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'],// set allowed HTTP methods
        allowHeaders: ['Content-Type','Authorization','Accept','Access-Control-Allow-Origin'],// set allowed HTTP fields
    }))
    .use(KoaLogger())
    .use(router.routes())
    .use(router.allowedMethods())

app.on('error',(err,ctx) => {
    console.error('server error',err,ctx)
})

app.listen(3000);
複製程式碼

預覽