一、前言


二、之前的坑

好,那我的工作又来的,后面就通过 5 个版本的迭代,把上面的 4 个坑感觉还是很好的填了的

三、优化过程

还有 tmp 是放在一些临时文件,好,上面的架构基本把接口和 mock 数据从 mock 服务器的代码中分离出来,那接下来就是主核心的 mock 服务器代码

具体的实现代码:

rule_mock.js
global.api = "testapi";   //mock接口标识
module.exports = {

    summary:function(){
        return "replace response data by local response now";
    },

    //mark if use local response
    shouldUseLocalResponse : function(req,reqBody){
      var fs=require('fs')
      var msdata=fs.readFileSync('./conf/ms.json',"UTF-8"); //读取mock开关配置文件
      var ms = JSON.parse(msdata);
      var isOpen = ms['isOpen'];
      if (isOpen==0) {                               //当isOpen为0时,把直接返回false跳过所有mock
        console.log("isOpen is :" +isOpen+",skip mock!");
        return false;
      };
      var file = fs.readFileSync('./api/mock_api.txt',"utf8");  //读取api文件
      var apilist = [];
      apilist=file.split(/\r?\n/ig);            //按行分割存为列表
      for (var i = 0;  i < apilist.length; i++) {    //循环mock,有多少个接口就mock多少次,支持多接口同时mock
        var mockapi=apilist[i];
        if(new RegExp(mockapi).test(req.url)){     //匹配是否为被mock接口
          global.api=mockapi
          return true;
          }
        };
      return false;  
    },

    dealLocalResponse : function(req,reqBody,callback){
            var fs=require('fs');
            console.log('mock api is: '+global.api);//使用global对象访问到"全局"变量
            fs.readFile('./data/mock_data.json',function(err,data){  //读取mock的数据,data为一个json对象
                if(err)  
                    throw err;     
                var arr = JSON.parse(data);
                try{
                  var respon=arr[global.api];  //取出json对象中对应api的数据
                  console.log("status  :" + respon.status);
                  console.log("headers  :" + JSON.stringify(respon.headers));
                  console.log("body  :" + JSON.stringify(respon.body));
                  var newDataStr=JSON.stringify(respon.body);
                  callback(respon.status,respon.headers,newDataStr); //组合成一个全新的响应对象并返回
                }

                catch(e){
                  console.log(e);
                  console.log("you should go to set mock data for api: "+global.api);  //作异常处理,当被mock的接口没有对应的mock数据时,提示并防止服务器退出
                }
            })

    }
};

通过注释来看设计思路就很清晰了,代码里面最核心的两个参数 global.api 和 isOpen,isOpen 用于控制是否要 mock,global.api 就是被 mock 接口和对应 mock 数据的一个关联,通过上面的方式,后面就不再需要通过 moco 来管理 response,直接组合就能解决问题了,通过上面的设计思路,能够解决我上面所提到的坑的前 3 点,好,具体操作来看一下

四,操作演示

以及测试的数据:

{,
"cim.msg%3Areply":
    {"status" : 202,"headers" :{"content-type" : " text/x-json;charset=UTF-8"},"body": {"code":"FA_OVERFLOW","var":{}}},
"setFlag":
    {"status" : 202,"headers" :{"content-type" : " text/x-json;charset=UTF-8"},"body": {"code":"FA_FORBIDDEN","var":{}}}
} 

所以大致的操作演示就是这样,其实还有第 4 点没说,当被 mock 的接口数到达一定数量时,mock 是否会有性能问题,因为总是整个文件的读,文件量大了,肯定会有问题的,所以就可以通过具体的业务模块的接口来分布到不同的文件中管理,逻辑如下:

分割方法:

rule_mock.dev.js
global.apigroup="testapigroup";

//省略部分已展示过的代码,具体实现逻辑和结合自己项目本身来实现,这个实现方式是我们产品的,未必通用

      try{
        //console.log("req.url is :" +req.url);
        var res=req.url.split('json?func=')[1];
        var useapi=res.split('&sid=')[0];
        //console.log("useapi is :" +useapi);
        global.apigroup=useapi.split('%3A')[0];
        console.log("apigroup is :" +global.apigroup);
      }
      catch(e){
        console.log("api pass");
      }

结合我们论客的接口设计特征,取出业务模块,比如 global.apigroup=cim.msg,然后之后根据 global.apigroup 的值读取对应模块的文件,比如读取 cim.msg.txt,同时加上异常处理

rule_mock.dev.js

//省略部分已展示过的代码
       try{
              var datapath='./data/'+global.apigroup+'.json';
              var filetmp = fs.readFileSync(datapath,"utf8");
            }
            catch(e){
              console.log('mock_data_file"'+global.apigroup+'" is not exist! skip to mock_data');
              var datapath='./data/mock_data.json';
            }

所有最后实现的效果,这样就能优化 mock 服务器的性能,可以看到明确的模块分组

同时对于未模块的 mock 接口,可以直接用回 mock_api 里面的数据,同时会跳过

就这样,我前面所说的 4 个坑就基本填完了

五,最后几句


↙↙↙阅读原文可查看相关链接,并与作者交流