数据访问对象模式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