首頁 >web前端 >js教程 >JS資料存取物件模式詳解

JS資料存取物件模式詳解

小云云
小云云原創
2018-01-27 17:19:181170瀏覽

本文主要為大家帶來一個JS設計模式之資料存取物件模式的實例講解。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧,希望能幫助大家。

問題

大部分網站會將一些資料(如:使用者Token)儲存在前端,用來實作頁間的傳值,對於某些大型Web應用程式來說,其儲存的資料可能會非常多,資料的管理會變得複雜,而一個大型專案是由多位程式設計師共同開發的,這時就會遇到一個問題:怎樣確保自己的資料不會覆蓋掉其他人的呢?因為在一個頁面中大家都是使用同一個WebStorage對象,總不能把大家使用過的Key記錄下來吧。這時候就可以使用資料存取對像模式來解決了。

引言

HTML5 提供了兩種在客戶端儲存資料的新方法:localStorage、sessionStorage,他們是Web Storage API 提供的兩種儲存機制,差別在於前者屬於永久性存儲,而後者是局限於當前視窗的資料傳遞,儲存在其中的資料會在當前會話結束時被刪除。 localStorage、sessionStorage的具體內容在這裡就不多做介紹了,我們主要探討一下在實際開發中怎樣合理使用他們。

資料存取物件模式(DAO)

資料存取物件模式就是將資料來源的存取與儲存裝置進行封裝,提供一個資料存取物件類別負責對儲存的資料進行管理與操作,規範資料儲存格式,類似後台的DAO層。

由於WebStorage採用Key-Value的方式存取數據,而且只能存字串(任何類型儲存的時候都會被轉為字串,讀取的時候需要進行類型轉換),所以我們可以對Key的格式進行規範,例如模組名稱+Key,開發人員+Key等,還可以在值中添加一段前綴用來描述數據,例如添加數據過期日期的時間戳,用來管理數據的生命週期。具體格式項目組可以自己定義,主要是便於管理,防止衝突,約定好規範後就可以開始定義資料存取對象了。

以下以localStorage為例,介紹一下資料存取物件類別的定義和使用。

程式碼範例

DAO類別基本結構

資料存取物件類別的基本結構如下,我們為鍵值新增了一段前綴用來避免鍵值衝突,並且在值中加入資料過期時間戳記以及分隔符,取得值的時候再進行判斷是否過期,這樣可以更靈活地管理儲存資料的生命週期。這裡也用到了回呼的方式,方便取得資料存取過程的具體結果,以及在必要時執行相關操作。

/**
 * LocalStorage数据访问类
 * @param {string} prefix Key前缀
 * @param {string} timeSplit 时间戳与存储数据之间的分割符
 */
var Dao = function (prefix, timeSplit) {
  this.prefix = prefix;
  this.timeSplit = timeSplit || '|-|';
}
// LocalStorage数据访问类原型方法
Dao.prototype = {
  // 操作状态
  status: {
    SUCCESS: 0,   // 成功
    FAILURE: 1,   // 失败
    OVERFLOW: 2,  // 溢出
    TIMEOUT: 3   // 过期
  },
  // 本地存储对象
  storage: localStorage || window.localStorage,
  // 获取带前缀的真实键值
  getKey: function (key) {
    return this.prefix + key;
  },
  // 添加(修改)数据
  set: function (key, value, callback, time) {
    ...
  },
  // 获取数据
  get: function (key, callback) {
    ...
  },
  // 删除数据
  remove: function (key, callback) {
    ...
  }
}

新增(修改)資料

/**
  * 添加(修改)数据
  * @param key 数据字段标识
  * @param value 数据值
  * @param callback 回调函数
  * @param time 过期时间
  */
  set: function (key, value, callback, time) {
    // 默认为成功状态
    var status = this.status.SUCCESS,
      key = this.getKey(key);
    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 (key, callback) {
    var key = this.getKey(key),
      status = this.status.SUCCESS,  // 获取数据状态
      value = null;  // 获取数据值

    try {
      // 从本地存储获取数据
      value = this.storage.getItem(key);
    } catch (e) {
      // 获取数据失败
      status = this.status.FAILURE;
      value = null;
    }

    // 如果成功获取数据
    if (status !== this.status.FAILURE) {
      var index = value.indexOf(this.timeSplit),
        timeSplitLen = this.timeSplit.length,
        // 获取时间戳
        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 (key, callback) {
    // 设置默认状态为失败
    var status = this.status.FAILURE,
      key = this.getKey(key),
      value = null;
    try {
      // 获取数据值
      value = this.storage.getItem(key);
    } catch (e) {
      // 数据不存在,不采取操作
    }
    // 如果数据存在
    if (value) {
      try {
        // 删除数据
        this.storage.removeItem(key);
        status = this.status.SUCCESS;
      } catch (e) {
        // 数据删除失败,不采取操作
      }
    }
    // 执行回调并传入参数,删除成功则传入被删除的数据值
    callback && callback.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSplit) + this.timeSplit.length));
  }

用法

var dao = new Dao('myModule_');
// 添加/修改数据
dao.set('token', 'abc', function () { console.log(arguments); });
// 获取数据
var value = dao.get('token', function () { console.log(arguments); });
console.log(value);
// 删除数据
dao.remove('token', function () { console.log(arguments); });

寫在最後

其實資料存取物件模式更適合與伺服器端的資料庫操作,例如在nodejs中操作MongoDB,透過對資料庫增刪改查操作的封裝,可以方便我們對前端儲存的管理,不必為操作資料庫感到煩惱, DAO已經為我們提供了便捷統一的接口,這樣在團隊開發中就不用擔心影響到其他人的數據了。

相關推薦:

php設計模式DAO(資料存取對像模式)

Yii學習總結之資料存取對象(DAO),yiidao_PHP教程

javascript物件導向之存取物件屬性的兩種方式分析_javascript技巧

以上是JS資料存取物件模式詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn