时间过得飞快,准备写些东西的时候才发现自己快一年半没有写blog了,写这些东西只是为了记录下来自己走过的坑,为下次遇见同类的问题能够迅速解决,毕竟人脑有限,存储下来以备不时之需。
一:背景(功能需求)
首先网站后台开发为nodejs,微信企业号中创建APP应用可以创建多个,每个APP应用的回调的URL是不同的,每个APP应用中都有消息通知,现在需要PC端把各个应用的消息通知集中起来放到PC端显示(消息通知全部来源于各个APP中),每条消息都有一条可访问的URL,微信中需要将Token和EncodingAESKey值写入到应用的配置信息里,实现与微信服务器的握手,之前的代码设计每个URL访问之前都有一个中间件过滤获取用户信息。但是PC端需要访问,就不能不能访问微信app中的URL,因为中间件这一环节就已经拦截下来了,即使可以但是PC端的页面和微信的页面展现方式不一致,又因为企业号中应用比较多,修改起来比较复杂,当时存储消息通知可访问URL时也是存的微信内可访问的URL,最后解决的方法用了适配的方法转换URL访问。
微信应用里也有一个消息通知总管理的页面,但是在微信里面不需要转换URL,只需要在微信可访问URL后面加个参数,告诉中间件此次访问不需要走中间件验证,遇到此参数直接放行就好。但是也是修改了14个企业应用。
PC端的消息通知需要实现企业号中各个APP消息通知URL转换到PC端需要访问的URL,而且有些功能可能企业号个别APP中独有的功能,而PC端没有页面与之对应,所以这类消息也要过滤掉,例如企业号中有考勤管理每天上下班打卡的消息通知,通知点击以后跳转到打卡的页面,而PC端没有,所以即使收到此类消息通知也不需要显示在PC页面上。
二:第一次尝试
第一次解决的方案是建立两个数组,一个数组存储指定URL的共有的一段路径,先写作var a = [];,例如:https://www.abc.com/wxapp/001/beyond_work_wechat/56ebb74aa10093f444628979/view/wx3bd6f3aa75c0c7e7",那么此URL在a数组中对应的就是a.push(''https://www.abc.com/wxapp/001/beyond_work_wechat/"),然后再声明一个b数组用来存储此URL转换的方法;
循环后台传回的数据,获得一条数据URL在数组a中索引的位置,如果没有找到,那么此消息是不需要显示在PC端的,找到索引后再用索引值找到需要处理的方法,然后把数据的URL传人然后返回一个新的URL;
此方法可以简单的实现,但是企业号中有15个应用,那么就算一个应用有一个访问的URL,那么我就要维护15个URL索引和15个URL处理方法,或许有一天我需要删除或者修改一个URL规则,那么我怎么保证删除或修改与之对应的URL处理方法是正确的呢,新增还可以理解,在两个数组后面添加就行了。所以此方法是一个解决少部分需求还是可以的,但是作为程序员,需求永远都在变,把自己代码写活才是我们的追求。所以在没有写完就被自己蠢哭了。错误的指向代码就不写出了,
三:第二次尝试
既然URL规则是多种多样的,但是都要走URL转换的功能,那么URL转换方法可以不变的,把每条URL转换规则作为一个对象传入到转换方法中就可以了,新增一条URL转换规则,只需要插入转换规则数组中即可,修改URL转换规则也可以随便修改,删除URL转换规则只需要不插入不就行了。话少说先上代码;
//立即执行函数 返回消息通知添加转换规则和转换数据方法的对象,主要为了应对环境变量污染
var pc_msg_data = (function() {
// 替换规则列表
var appmsg_notice_urladapte_rule = [];
/**
* [push_rule 添加替换规则]
* @param {[type]} rule_obj [替换规则]
* @return {[type]} [description]
*/
var push_rule = function(rule_obj) {
appmsg_notice_urladapte_rule.push(rule_obj);
};
/**
* [url_format 数据参数批量替换]
* @param {[type]} format [description]
* @param {[type]} array [description]
* @return {[type]} [description]
*/
var url_format = function(format, array) {
for (var i = 1; i < array.length; i++) {
format = format.replace(new RegExp("\\{" + i + "\\}", "g"), array[i]);
}
return format;
}
/**
* [get_pc_url 得到pc端可用的url]
* @param {[type]} url [description]
* @return {[type]} [description]
*/
var get_pc_url = function(url) {
var pc_url = "";
for (var i = 0; i < appmsg_notice_urladapte_rule.length; i++) {
var match_obj = appmsg_notice_urladapte_rule[i];
var match_array = url.match(match_obj.rule);
if (match_array && match_array.length > 1) {
pc_url = url_format(match_obj.format, match_array);
break;
}
}
return pc_url;
};
/**
* [wx_data_adapter 微信URL数据转换适配到数据过滤]
* @param {[type]} data [微信数据]
* @return {[type]} [description]
*/
var wx_data_adapter = function(data) {
for (var i = 0; i < data.length; i++) {
var item = data[i];
item.pc_url = get_pc_url(item.url);
}
return _.filter(data, function(obj) {
return obj.pc_url.length > 0;
});
}
/**
* [get_rule_list 获取转换规则名称列表,为了]
* @return {[type]} [description]
*/
var get_rule_list = function(){
var name_array = [];
for(var i=0;i<appmsg_notice_urladapte_rule.length;i++){
name_array.push(appmsg_notice_urladapte_rule[i].name);
}
return name_array;
};
return {
push_rule: push_rule,
get_rule_list:get_rule_list,
wx_data_adapter: wx_data_adapter
}
}());
//立即执行函数 主要考虑添加转换规则过多,如果都放在pc_msg_data中反而职责不清楚了,此只为添加规则列表
var pc_msg_data_addrolelist = (function() {
var rule_obj = {
rule: /^https:\/\/www.abc.com\/wxapp\/001\/beyond_work_wechat\/(\w+)\/view\/(\w+)/,
name: '加班流程审批结束',
format: "https://www/abc.com/{1}/{2}"
};
pc_msg_data.push_rule(rule_obj);
}());
var data = [{
msg: '你有一条加班流程审批结束',
url: "https://www.abc.com/wxapp/001/beyond_work_wechat/56ebb74aa10093f444628979/view/wx3bd6f3aa75c0c7e7",
create_tm: 454662422224
}, {
"msg": "您有一条假期调整流程 前端白小白的假期调整流程,需要征求您的意见",
"url": "https://www.abc.com/wxapp/004/back_leave_form_wechat/56a73f34fbb4581a05bf376b/deal_with/wx3bd6f3aa75c0c7e7",
"create_tm": 454662422224,
},
{
"msg": "当第一缕晨光射穿薄雾,大地迎来了一个温馨.....",
"url": "https://www.abc.com/wxapp/001/clockin",
"create_tm": 454662422224,
}
];
console.log(pc_msg_data.get_rule_list());
console.log(pc_msg_data.wx_data_adapter(data));
现在就就不怕URL转换规则的改变了,新增修改删除都可以满足,这段代码是放在前端实现转换的,如果要放在后台那也无所谓了,如果想要实现消息分页获取,那么就需要再在存储消息通知的时候加上是否在PC端显示即可。消息的URL转换规则和方法照常不变。以变化适应变化。
四:总结
项目产品需求总是再变,写代码时要时时刻刻想着潜在的需求,让代码适应未来可能添加的需求,静态语言中的23种设计模式,是可以用在JavaScript中的,但是不是要我们什么时候都用,合适的才是最美的。程序员的职能不单单是为了实现功能那么简单,代码也是可以实现的更优雅些的。
多想多悟,程序来源于生活,抽象很重要!