前言

刚入职新公司不久,经营妹子提了个需要,她整顿了一份400条数据记录的excel,须要执行两步操作,一个是批量审核,一个是批量合并。后盾界面都是能够操作的,但都没有批量性能。让我能不能写个脚本解决下。本着给新共事建立一个良好形象的目标,我欣然接受了这个需要。对于从天而降的需要,只能拿出本人多少年与产品经营一直交锋,攒下来的本事进行应答了,俗称见招拆招。

梳理要做的事件

首先对整个事件要弄清楚本人须要干什么,怎么干。经营给的是一份excel表格。外面是它整顿的400条具备映射关系的数据格式形如:

fieldNamenewValueoldValue
Kkk1112222

第一件事件是有一张待审核记录表,权且叫做check_info表吧,这张表里寄存的是400条爬虫引入的待审核数据,对应的正是excel里的400条数据,形如:

fieldNamevalue审核状态
kkk111待审核

须要将这400条数据,批量审核通过,界面是没有批量性能的。某条记录审核胜利后,就会在另外一个表生成一条数据,加上之前旧的值曾经存在一条数据,一共两条数据,这张表权且叫作field_detail吧,形如:

fieldNameValueKeymap_key
kkk1111Null
Kkk2222Null

222那条数据是oldValue对应的数据,111是下面审核通过新加的数据。

第二件要做的事件就是,执行上面这条语句:

update field_detail set map_key = 1 where fieldName='kkk' and key=2;

很简略,然而同样没有批量接口,另外这个接口做的事件不止执行这条语句这么简略,还做了许多和缓存清理,更新无关的事件。所以只能写脚本批量调用单条的接口。事件曾经形容完了。上面就是开干了。

给出解决方案

单条审核的接口是get申请,形如:/check_info/check?id=&value=xxx,审核的接口应用get,有点奇怪呀。因为是依据id进行审核的,所以必须找出excel表里400条记录对应在check_info表的id。这个能够把excel记录转化为select语句,而后400条应用union连贯一下。就能够把400条id找进去了。留神此处的参数外面还须要把value传给后盾,因为这个接口的定义是能够在审核的时候批改本人从新定义的value,然而此处咱们只有把原值传过来即可。找进去之后放到一个json数组外面,而后应用本人的身份登录到后盾零碎。按F12关上chrome的调试工具,在sources这个tab下新建一个snippet,这个外面就能够写js代码了。此处能够写个for循环,400条数据一一ajax调用相应的接口。胜利持续调用下一条,失败就中断循环。具体代码上面会贴出来。这样第一件事件就算实现了。第二件事件要害就是把oldValuenewValue的key找进去。因为单条的接口参数有三个别离是:fieldNameoldKeynewKey。此处还是应用sql解决。思路就是将新的和老的合并成一条记录,属性有fieldNameoldKeynewKey,而后将400条记录再union起来。并将查问后果导出成json格局。同样应用相似第一步的形式一一调用接口。

具体过程

首先依据经营提供的excel找出待审核的id,这个用excel的CONCATENATE函数很灵。形如:

=CONCATENATE("select id,value from check_info where fieldName= B2 and value= C2 union")

B2示意取第二行第二列,C2示意取第二行第三列。最初将sql拼接起来,就能够将待审核的记录的idvalue从线上库里捞进去。庆幸就400条,因为DMS限度单次查问不大于500条。将查问的数据导出成json格局。

开始写批量申请的脚本:

庆幸400条都显示执行胜利了。当然因为是间接操作线上环境,开始不要批量跑,弄几条试试是很有必要的。而后是查看处理结果,然而可怜的是出问题了。按情理应用形如上面的sql语句查看,后果应该是400条数据:

select * from field_detail where fieldName=kkk and value = 111 union ...

然而后果就395条,为什么少了5条呢?通过一些sql我找出了缺失的那5条。发给了经营。询问她这几条数据是不是有什么问题。因为我自信的认为我的操作是没问题的。肯定是经营给的数据有问题。经营妹子也不赖,迅速找出了这几条的法则。value的内容都蕴含了+号。理论这几条数据曾经进入了field_detail,只不过+号变成了空格。此时我立马晓得问题出在哪了。申请参数被我encodeURI解决过了。其实在上家公司遇到过这种状况。也是本人不够器重,"二进宫"了。经营妹子痛快的说她本人改下就能够了。就5条嘛。但此时我的心里是有点自责的。同样的坑踩了两次,实属不应该啊。那我来解释下为什么+号会变成空格吧。

RFC-2396这个规范定义了URI中+号为保留字符,encodeURI不会对保留字符进行编码。比方:

encodeURI("国+家");//%E5%9B%BD+%E5%AE%B6

而加号这个保留字符的含意就是空格。所以传入后端会变成空格。要解决这个问题有两个计划,一是将value放到payload中。改成post申请,当然以后这个场景必定是不行的。第二个计划就是应用encodeURIComponent,这个函数会对保留字符进行编码,比方:

encodeURIComponent("国+家");//%E5%9B%BD%2B%E5%AE%B6

+号变成了%2B。这样传入后端还会解码为+号了。

对于百分号编码具体解释请参考:http://www.lmwlove.com/ac/id1030

就这样第一步算蒙混过关了,接下来须要进行批量合并了。首先还是把须要传入的参数应用sql查询处理,解决的sql形如:

select `fieldName`,(select `key` from field_detail where fieldName = 'kkk' and value = '111') as newKey,`key` as oldKey from field_detail where  fieldName = 'kkk' and value = '222' union...

批量合并的脚本,形如:

//进展办法,防止过载function sleep(ms) {   return new Promise(resolve => setTimeout(resolve, ms));}//封装ajax申请const ajaxGet = (url)=>new Promise(function(resolve,reject){    var xhr = new XMLHttpRequest();    xhr.open('GET', url);    xhr.send();    xhr.onload = function() {                if(xhr.status == 200) {                  resolve(xhr);                }else{                  reject("调用失败");                }    };});async function doMerge(){    var mergeParamArray = [{"fieldName":"kkk","newKey":123,"oldKey":456}];//理论有400条    for(var i=0;i< mergeParamArray.length;i++){       //调用合并接口       var mergeParam = mergeParamArray[i];       var url = "/field_detail/merge?field="+mergeParam.fieldName+"&oldKey="+mergeParam.oldKey+"&newKey="+mergeParam.newKey;       await ajaxGet(url);       console.log("merge field ",JSON.stringify(mergeParam)," success");       await sleep(1000);    }}doMerge();

庆幸400条都胜利了。经营妹子示意了感激。

总结与反思

下面这种案例只能解一时之需,真正迷信的方法还是增加性能。满足日常经营需要。整个过程下来,兴许是本人的确做过许多相似的事件吧,简直没有什么卡顿。然而有几个中央还是做得不够好,比方下面那个百分号编码问题,还有整个过程本人和经营确认的环节也没做好。实践上这种需要都须要本人执行一步,经营确认一步。如果经营确认的时候不够认真,本人也须要把要害信息传递给她。表明本人执行完当某个操作执行,成果是什么样的。还有一点也是要值得思考的,毕竟是批量调用接口,难保某次调用有问题,导致整个执行中断。此时须要记录下以后的进度。找出出错的是哪条记录,便于下次复原执行。还有一点也很要害,就是假如执行过程中发现问题了,为了及时止损,须要中断工作执行。此时能够思考强制敞开以后标签页。这样for循环的js也会终止执行。总之胆子要大,但心要细。