什麼是收口
所謂條條大路通羅馬,但如果讓我來設計通向羅馬的各種大路,我至少會做兩件事情:
① 讓羅馬只有一個入口
② 讓羅馬只有一個出口
這樣做的好處是,無論你路從哪來,我可以統一在入口處給你打上各種標誌,我也可以在你離開羅馬時給你留點紀念。當然羅馬自然不只一個出口入口,但是每個出口入口一定有一套相同的規定,否則就會出問題。
具體到當今的工作場景,高速公路又是一個收口的好例子,進入高速公路時候得經過收費站做點標誌,離開時候也會做點操作,如果沒有這種收口,不論是繳費工作,流量統計或者其他都是無法統計的。
正常生活中有各種收口的行為,我們會發現,收口雖然會讓效率變低,但卻可以更好的管理,同樣的道理是可以應用到前端乃至整個程式開發的,今天我們就來聊一聊前端中的各種收口。
文中僅僅是個人經驗,如果有誤請指出。
一個收口的例子
前面我們說了工作中收口帶來的各種好處(壞處是面向使用者會增加成本),而我們前端開發中會有哪些收口呢?
一般來說,對於前端,請求收口即是ajax的收口,而經常有朋友會問我一些問題:重複的請求如何讓他第二次不請求呢?
其實解決這個問題很簡單的一個方案就是對ajax進行收口處理:
1 2 3 4 |
var ajaxProxy = function(params) { //做一些額外的工作,比如處理params引數 $.ajax(params) }; |
這裡的處理辦法就是統一在底層篡改ajax success回撥,對資料做一層處理,然而對請求介面進行收口的好處遠遠不止於此。
封裝請求引數
首先,我們可以對每個請求的請求引數在底層加入額外引數,比如我們與server端約定,每次請求我們都會額外帶一個head引數,會攜帶一些非業務公共資料:
1 2 3 4 5 6 |
head: { channel: 'webapp', //渠道標誌 version: '2.2.0', //版本資訊 ct: 3, //平臺資訊 extend: null//可能需要的擴充套件資訊 } |
每一個請求如果額外帶這些資訊的話,可以解決很多問題:
① server端知道當前請求來源於哪個渠道(SEM渠道、微信流量入口、搜尋流量入口……)、哪一個版本、哪一個平臺(iOS、Android、H5),可能Server就能對這個請求做定製化處理了
② 協助KPI考核,比如市場人員要推廣自己的產品,而後臺要統計他今天成功推廣多少單,就會為這個使用者生成一個二維碼,具體的url是這樣的:
http://domain.com?channel=yexiaochai
那麼,我的沒一個請求(包括生成訂單)都將把channel欄位發給Server端,Server如果存於資料庫,每天就能很簡單生成所有使用者的訂單完成量
③ SEM渠道是一大流量來源(買搜尋關鍵詞),如果我們想拿到每一個關鍵詞對我們系統每一個頁面的訪問量的話,也可以在這種公共請引數做處理
④ 根據以上功能,我們甚至可以根據這些特性配合通用的統計平臺建立初略的前端漏斗模型
統一資料處理
一般來說,每個請求介面,server端返回的資料有一固定格式:
1 2 3 4 5 |
{ data: {},//真實資料 errno: 0,//錯誤碼 msg: "success"//資訊 } |
正常的邏輯我們只需要處理data資料即可,而錯誤碼不為0的情況,我們多是彈一個toast提示msg錯誤資訊,所以我們會統一修改請求的回撥,當然也會對一些錯誤碼做特殊處理(未登陸、未授權),比如這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//統一處理請求返回資料 var commonDataHandler = function (data) { //記錄請求返回 if (!data) { showToast('伺服器出錯,請稍候再試'); return; } if (_.isString(data)) data = JSON.parse(data); //正常情況,不執行其它邏輯 if (data.errcode === 0) return true; //處理請求未登陸的特殊情況 if (data.errcode == ERROR_CODE['NOT_LOGIN']) { showToast(data.errmsg, function () { //執行統一邏輯,跳到登陸頁面,要求登陸成功後跳回來 }); return false; } //處理其它需要特殊處理的錯誤碼,需要業務開發對介面做定製化,將處理邏輯寫到具體頁面 if(this.errCodeCallback[data.errcode]) { this.errCodeCallback[data.errcode](data.errcode, data.errmsg, data); return false; } //通用錯誤處理,直接彈出toast if (window.APP && data && data.errmsg) window.APP.showToast(data.errmsg, this.errorCallback); return false; }; |
當然,最開始說的重複請求不再請求也可以做到這個地方,但是具體操作會有很多細節點需要考慮。
不使用ajax
因為hybrid模式的出現,前端除了ajax外,可能會有更多的選擇,比如在Native容器中,前端便不使用ajax發出請求,直接由Native代理髮出,如果請求沒做封口的話,便需要改動所有的業務程式碼,這個是十分不科學的。
結語
這裡僅僅是提一個小小的點想向各位說明程式收口的重要性,其實我們程式中很多細小的點皆需要做收口處理。
localstorage使用收口
我們前面說過如果不想重複請求便需要使用快取技術,對應到前端是localstorage,無論何時,我們使用快取都必須考慮如何更新和快取過期問題,這個時候我們需要對齊收口。
跳轉收口
在做單頁應用時,我們為了不破壞路由,需要對跳轉做收口,我們甚至需要對window.location這種跳轉做收口處理,得封裝為一個函式。
關於實際工作中的收口的例子太多了,細小入setTimeout的收口,事件機制的收口,大到賬號體系、錢包體系等的收口處理,我們在實際工作中應該具備這種收口的思想。