关于前端开发中的“收口”思想
什么是收口
所谓条条大路通罗马,但如果让我来设计通向罗马的各种大路,我至少会做两件事情:
① 让罗马只有一个入口
② 让罗马只有一个出口
这样做的好处是,无论你路从哪来,我可以统一在入口处给你打上各种标志,我也可以在你离开罗马时给你留点纪念。当然罗马自然不只一个出口入口,但是每个出口入口一定有一套相同的规定,否则就会出问题。
具体到当今的工作场景,高速公路又是一个收口的好例子,进入高速公路时候得经过收费站做点标志,离开时候也会做点操作,如果没有这种收口,不论是缴费工作,流量统计或者其他都是无法统计的。
正常生活中有各种收口的行为,我们会发现,收口虽然会让效率变低,但却可以更好的管理,同样的道理是可以应用到前端乃至整个程序开发的,今天我们就来聊一聊前端中的各种收口。
文中仅仅是个人经验,如果有误请指出。
一个收口的例子
前面我们说了工作中收口带来的各种好处(坏处是面向用户会增加成本),而我们前端开发中会有哪些收口呢?
一般来说,对于前端,请求收口即是ajax的收口,而经常有朋友会问我一些问题:重复的请求如何让他第二次不请求呢?
其实解决这个问题很简单的一个方案就是对ajax进行收口处理:
1 var ajaxProxy = function(params) { 2 //做一些额外的工作,比如处理params参数 3 $.ajax(params) 4 };
这里的处理办法就是统一在底层篡改ajax success回调,对数据做一层处理,然而对请求接口进行收口的好处远远不止于此。
封装请求参数
首先,我们可以对每个请求的请求参数在底层加入额外参数,比如我们与server端约定,每次请求我们都会额外带一个head参数,会携带一些非业务公共数据:
1 head: { 2 channel: 'webapp', //渠道标志 3 version: '2.2.0', //版本信息 4 ct: 3, //平台信息 5 extend: null//可能需要的扩展信息 6 }
每一个请求如果额外带这些信息的话,可以解决很多问题:
① server端知道当前请求来源于哪个渠道(SEM渠道、微信流量入口、搜索流量入口......)、哪一个版本、哪一个平台(iOS、Android、H5),可能Server就能对这个请求做定制化处理了
② 协助KPI考核,比如市场人员要推广自己的产品,而后台要统计他今天成功推广多少单,就会为这个用户生成一个二维码,具体的url是这样的:
http://domain.com?channel=yexiaochai
那么,我的没一个请求(包括生成订单)都将把channel字段发给Server端,Server如果存于数据库,每天就能很简单生成所有用户的订单完成量
③ SEM渠道是一大流量来源(买搜索关键词),如果我们想拿到每一个关键词对我们系统每一个页面的访问量的话,也可以在这种公共请参数做处理
④ 根据以上功能,我们甚至可以根据这些特性配合通用的统计平台建立初略的前端漏斗模型
统一数据处理
一般来说,每个请求接口,server端返回的数据有一固定格式:
1 { 2 data: {},//真实数据 3 errno: 0,//错误码 4 msg: "success"//信息 5 }
正常的逻辑我们只需要处理data数据即可,而错误码不为0的情况,我们多是弹一个toast提示msg错误信息,所以我们会统一修改请求的回调,当然也会对一些错误码做特殊处理(未登陆、未授权),比如这样:
1 //统一处理请求返回数据 2 var commonDataHandler = function (data) { 3 //记录请求返回 4 if (!data) { 5 showToast('服务器出错,请稍候再试'); 6 return; 7 } 8 if (_.isString(data)) data = JSON.parse(data); 9 //正常情况,不执行其它逻辑 10 if (data.errcode === 0) return true; 11 12 //处理请求未登陆的特殊情况 13 if (data.errcode == ERROR_CODE['NOT_LOGIN']) { 14 showToast(data.errmsg, function () { 15 //执行统一逻辑,跳到登陆页面,要求登陆成功后跳回来 16 }); 17 return false; 18 } 19 //处理其它需要特殊处理的错误码,需要业务开发对接口做定制化,将处理逻辑写到具体页面 20 if(this.errCodeCallback[data.errcode]) { 21 this.errCodeCallback[data.errcode](data.errcode, data.errmsg, data); 22 return false; 23 } 24 //通用错误处理,直接弹出toast 25 if (window.APP && data && data.errmsg) window.APP.showToast(data.errmsg, this.errorCallback); 26 return false; 27 };
当然,最开始说的重复请求不再请求也可以做到这个地方,但是具体操作会有很多细节点需要考虑。
不使用ajax
因为hybrid模式的出现,前端除了ajax外,可能会有更多的选择,比如在Native容器中,前端便不使用ajax发出请求,直接由Native代理发出,如果请求没做封口的话,便需要改动所有的业务代码,这个是十分不科学的。
结语
这里仅仅是提一个小小的点想向各位说明程序收口的重要性,其实我们程序中很多细小的点皆需要做收口处理。
localstorage使用收口
我们前面说过如果不想重复请求便需要使用缓存技术,对应到前端是localstorage,无论何时,我们使用缓存都必须考虑如何更新和缓存过期问题,这个时候我们需要对齐收口。
跳转收口
在做单页应用时,我们为了不破坏路由,需要对跳转做收口,我们甚至需要对window.location这种跳转做收口处理,得封装为一个函数。
关于实际工作中的收口的例子太多了,细小入setTimeout的收口,事件机制的收口,大到账号体系、钱包体系等的收口处理,我们在实际工作中应该具备这种收口的思想。