數據訪問對象模式Data Access Object Pattern
即DAO
模式,用於把低級的數據訪問API
或操做從高級的業務服務中分離出來,準確來講數據訪問對象模式不屬於一般定義的設計模式範疇,但數據訪問對象模式是一種很是有用的數據訪問管理構建技巧。javascript
數據訪問對象模式就是對數據源的訪問與存儲進行封裝,提供一個數據訪問對象類負責對存儲的數據進行管理和操做,規範數據存儲格式,相似於後臺的DAO
層。
HTML5
提供了兩種在客戶端存儲數據的新方法: localStorage
、sessionStorage
,他們是Web Storage API
提供的兩種存儲機制,區別在於前者屬於永久性存儲,然後者是侷限於當前會話以及衍生窗口的數據傳遞。因爲WebStorage
採用Key-Value
的方式存取數據,並且只能存字符串(任何類型存儲的時候都會被轉爲字符串,讀取的時候須要進行類型轉換),因此咱們能夠對Key
的格式進行規範,好比模塊名+Key
,開發人員+Key
等,還能夠在值中添加一段前綴用來描述數據,如添加數據過時日期的時間戳,用來管理數據的生命週期。具體格式項目組能夠本身定義,主要是便於管理,防止出現衝突,在前端方面其實主要是對於本地存儲進行了一次封裝,用以進行一個規範性約束,約定好規範後就能夠開始定義數據訪問對象了。html
/** * LocalStorage數據訪問類 * @param {string} prefix Key前綴 * @param {string} timeSplit 時間戳與存儲數據之間的分割符 */ var DAO = function (prefix, timeSplit) { this.prefix = prefix; this.timeSplit = timeSplit || "|-|"; } // 原型方法 DAO.prototype = { constructor: DAO, // 操做狀態 status: { SUCCESS: 0, // 成功 FAILURE: 1, // 失敗 OVERFLOW: 2, // 溢出 TIMEOUT: 3 // 過時 }, // 本地存儲對象 storage: localStorage || window.localStorage, /** * 獲取帶前綴的真實鍵值 * @param key 數據字段標識 */ getKey: function (key) { return this.prefix + key; }, /** * 添加(修改)數據 * @param key 數據字段標識 * @param value 數據值 * @param callback 回調函數 * @param time 過時時間 */ set: function (oriKey, value, callback, time) { let status = this.status.SUCCESS; // 默認爲成功狀態 let key = this.getKey(oriKey); try{ time = new Date(time).getTime() || time.getTime(); // 獲取過時時間戳 }catch(e){ time = new Date().getTime() + 1000 * 60 * 60 * 24 * 30; // 未設置過時時間時默認爲一個月 } try{ this.storage.setItem(key, time + this.timeSplit + value); // 向本地存儲中添加(修改)數據 }catch(e){ status = this.status.OVERFLOW; // 發生溢出 } callback && callback.call(this, status, key, value); // 執行回調並傳入參數 }, /** * 獲取數據 * @param key 數據字段標識 * @param callback 回調函數 */ get: function (oriKey, callback) { let key = this.getKey(oriKey); let status = this.status.SUCCESS; // 獲取數據狀態 let value = null; // 獲取數據值 try{ value = this.storage.getItem(key); // 從本地存儲獲取數據 }catch(e){ status = this.status.FAILURE; // 獲取數據失敗 value = null; } // 若是成功獲取數據 if (status !== this.status.FAILURE) { let index = value.indexOf(this.timeSplit); let timeSplitLen = this.timeSplit.length; let time = value.slice(0, index); // 獲取時間戳 // 判斷數據是否未過時 if(new Date(1 * time).getTime() > new Date().getTime() || time === 0) { value = value.slice(index + timeSplitLen); // 獲取數據值 }else { value = null; // 數據已過時,刪除數據 status = this.status.TIMEOUT; this.remove(key); } } callback && callback.call(this, status, value); // 執行回調 return value; // 返回結果值 }, /** * 刪除數據 * @param key 數據字段標識 * @param callback 回調函數 */ remove: function (oriKey, callback) { let status = this.status.FAILURE; // 設置默認狀態爲失敗 let key = this.getKey(oriKey); let value = null; try { value = this.storage.getItem(key); // 獲取數據值 }catch(e){ // 數據不存在,不採起操做 } if(value){ // 若是數據存在 try{ // 刪除數據 this.storage.removeItem(key); status = this.status.SUCCESS; }catch(e) { // 數據刪除失敗,不採起操做 } } // 執行回調並傳入參數,刪除成功則傳入被刪除的數據值 let param = status > 0 ? null : value.slice(value.indexOf(this.timeSplit) + this.timeSplit.length); callback && callback.call(this, status, param); } }; (function(){ let dao = new DAO("user-verify"); dao.set("token", "111", (...args) => console.log(args)); // [0, "user-verifytoken", "111"] let value = dao.get("token", (...args) => console.log(args)); // [0, "111"] console.log(value); // 111 dao.remove("token", (...args) => console.log(args)); // [0, "111"] })();
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/235136284 https://zkhdev.github.io/2017/07/31/js-dao/ https://www.runoob.com/design-pattern/data-access-object-pattern.html