什么是收口
所謂條條大路通羅馬,但如果讓我來設計通向羅馬的各種大路,我至少會做兩件事情:
① 讓羅馬只有一個入口
② 讓羅馬只有一個出口
這樣做的好處是,無論你路從哪來,我可以統一在入口處給你打上各種標志,我也可以在你離開羅馬時給你留點紀念。當然羅馬自然不只一個出口入口,但是每個出口入口一定有一套相同的規定,否則就會出問題。
具體到當今的工作場景,高速公路又是一個收口的好例子,進入高速公路時候得經過收費站做點標志,離開時候也會做點操作,如果沒有這種收口,不論是繳費工作,流量統計或者其他都是無法統計的。
正常生活中有各種收口的行為,我們會發現,收口雖然會讓效率變低,但卻可以更好的管理,同樣的道理是可以應用到前端乃至整個程序開發的,今天我們就來聊一聊前端中的各種收口。
文中僅僅是個人經驗,如果有誤請指出。
一個收口的例子
前面我們說了工作中收口帶來的各種好處(壞處是面向用戶會增加成本),而我們前端開發中會有哪些收口呢?
一般來說,對於前端,請求收口即是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的收口,事件機制的收口,大到賬號體系、錢包體系等的收口處理,我們在實際工作中應該具備這種收口的思想。