Safari無痕模式下,storage被禁用問題

BothEyes1993發表於2018-12-11

前言

Safari開啟無痕模式後,localStorage和sessionStorage為空,對其進行set操作也會報錯,也就是說這種情況下,storage是被禁止使用了。接下來說一下解決方法。

解決方案

我們專案框架上的解決方法是對storage進行一層封裝,遇到這種開啟無痕模式的情況,會定義一個window的全域性變數,把之前準備存放到storage的內容改為存到這個全域性變數中。

注意,無痕模式下localStorage和sessionStorage物件本身依然是存在的,只是呼叫setItem方法是會報錯。下面是無痕模式下報錯的截圖:

所以正確的判斷程式碼應該是這樣:

  try {
      sessionStorage.setItem('private_test', 1);
    } catch (e) {
      //無痕模式
    }
複製程式碼

我們會另外定義一個NameStorage物件,在原生storage失效時使用:

 // 隱私模式下面,把臨時值存到window.name中去
  function NameStorage(type) {
    this.store = NameStorage[type];
  }


  Object.assign(NameStorage.prototype, {
    getItem: function(key) {
      return this.store[key];
    },
    setItem: function(key, value) {
      this.store[key] = value;
      this._saveNameValue();
    },
    removeItem: function(key) {
      delete this.store[key];
      this._saveNameValue();
    },
    clear: function() {
      this.store = {};
      this._saveNameValue();
    },
    _saveNameValue: function() {
      var ret = {
        session: NameStorage.session,
        local: NameStorage.local
      }

      window.name = JSON.stringify(ret);
    }
  });
複製程式碼

上面會把所有的local和session資料儲存到window.name上去,然後在每個頁面啟動時,呼叫一下keepName方法,把window.name的資料拿下來放到NameStorage上面。這時候,只需要呼叫new NameStorage('local')來代替localStorage進行操作就行了

 function keepName () {
    if (keepName.done) {
      return;
    }

    var ret;

    if (window.name) {
      try {
        ret = JSON.parse(window.name);
      } catch (e) {
        ret = {};
      }
    }

    if (!_.isPlainObject(ret)) {
      ret = {};
    }


    if (!ret.session) {
      ret.session = {};
    }

    if (!ret.local) {
      ret.local = {};
    }


    NameStorage.session = ret.session;
    NameStorage.local = ret.local;
    keepName.done = true;
  }
複製程式碼

另外一些補充

● 無痕模式下,localStorage和sessionStorage的報錯資訊是:QuotaExceededError,code為22,這個其實是storage儲存空間用完了報的錯,就比如當前瀏覽器storage記憶體為5mb,你已經儲存了5mb的資料後,再進行setItem操作就會報這個錯誤。

● 所以我猜想無痕模式下,瀏覽器是把storage的記憶體先清空,然後再設定最大值為0,這樣呼叫setItem就直接報錯了。

● 另外無痕模式下cookie是可以使用的,大概因為cookie是跟伺服器有關,而storage是屬於瀏覽器的特性吧。

● 最後還有一種情況,就是無痕模式下開啟了某個頁面,然後把瀏覽器關閉再開啟,這個時候會開啟訪問的頁面,但是window.name已經丟失了,所以就拿不到以前儲存的資料了。這種情況只能頁面做容錯處理了。

相關文章