Коли закінчуються елементи в локальній пам’яті HTML5?


337

Як довго доступні дані, що зберігаються в localStorage (як частина DOM Storage in HTML5)? Чи можу я встановити термін придатності для даних, які я вклав у localStorage?


3
не використовуйте localStorage, якщо можливо, тому що ніколи не закінчується автоматично, там ви можете використовувати sessionStorage, що є більш бажаним
Dharmendrasinh Chudasama

Відповіді:


215

Термін дії не вказаний. Це повністю залежить від користувача.

https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

Звичайно, можливо, що чогось ваша програма не зберігатиме у клієнта пізніше. Користувач може явно позбутися локального сховища, або браузер може зіткнутися з космічними міркуваннями. Добре програмувати захисно. Як правило, все залишається "назавжди" на основі певного практичного визначення цього слова.

редагувати - очевидно, ваша власна програма може активно видаляти речі, якщо вона вирішить, що вона занадто стара. Тобто ви можете явно включити якусь часову позначку у збережені вами дані, а потім використати це пізніше, щоб вирішити, чи слід видаляти інформацію чи ні.


1
Тож чи може користувач розраховувати на доступні дані через, скажімо, рік? Чи може розробник розраховувати на доступні дані, якщо користувач явно не видаляє їх?
Андрес Ріофріо,

6
@AndresRiofrio Я не можу знайти жодної документації від Mozilla або Microsoft або W3C, яка б передбачала будь-який обов'язковий термін дії. Тому я думаю, що відповідь полягає в тому, що так, агент користувача повинен зберігати збережені речі назавжди або до тих пір, поки користувач прямо не попросить його видалити (або, мабуть, поки ваша власна програма не видалить власні речі).
Pointy

3
Це також означає, що ваш браузер постійно зростає. Ви використовуєте додаток один раз, він зберігає його речі у вашому браузері, і він залишається там назавжди ....
Пітер ван Кампен

1
Кількість даних localStorage, які ви можете зберігати на одному веб-сайті, становить близько 10 Мб, але середній сайт не може зберігати набагато більше, ніж кілька рядків, тому я б не заперечував щодо місця для зберігання
Хуан

1
Firefox тут має задокументовану політику щодо виселення .
ShreevatsaR

269

Я б запропонував зберігати часові позначки в об'єкті, який ви зберігаєте в localStorage

var object = {value: "value", timestamp: new Date().getTime()}
localStorage.setItem("key", JSON.stringify(object));

Ви можете проаналізувати об'єкт, отримати часову позначку та порівняти з поточною датою та, якщо необхідно, оновити значення об’єкта.

var object = JSON.parse(localStorage.getItem("key")),
    dateString = object.timestamp,
    now = new Date().getTime().toString();

compareTime(dateString, now); //to implement

3
Ну, навіть якщо час клієнта не відповідає, ви все одно можете знайти спосіб використання свого часу на сервері. Як би повторюючи позначку часу в діві.
Верховний Дельфін

Ви б проаналізували та порівняли часові позначки у часовому інтервалі (наприклад, settimoutкожні 5 секунд) або для кожного запиту, який клієнт відправляє на сервер?
ibubi

кращий спосіб - порівняти дати для кожного запиту користувача
Terai

36

Ви можете використовувати lscache . Він обробляє це автоматично для вас, включаючи випадки, коли розмір пам’яті перевищує обмеження. Якщо це станеться, воно починає обрізати предмети, найближчі до зазначеного терміну.

З readme:

lscache.set

Stores the value in localStorage. Expires after specified number of minutes.

Arguments
key (string)
value (Object|string)
time (number: optional)

Це єдина реальна різниця між методами звичайного зберігання. Отримати те ж саме, отримуйте, видаляйте тощо.

Якщо вам не потрібна така велика функціональність, ви можете просто зберегти штамп часу зі значенням (через JSON) і перевірити його на термін дії.

Зауважимо, що є вагома причина, чому місцевий сховище залишається користувачем. Але такі речі, як lscache, дуже корисні, коли потрібно зберігати надзвичайно тимчасові дані.


Дякую! Це приголомшливо для того, що мені потрібно - дані просто повинні бути там, якщо користувач зробить завантаження або браузер закриється, перш ніж він збереже свою роботу, але є занадто багато даних для файлів cookie. Я використовую його спільно з pieroxy.net/blog/pages/lz-string/index.html .
Пітер Смартт

34

Брайнер Феррейра, приніс хороший момент: зберігання ключа рідного брата, де знаходиться інформація про термін дії. Таким чином, якщо у вас є велика кількість ключів, або якщо ваші значення великі об'єкти Json , вам не потрібно їх розбирати, щоб отримати доступ до часової позначки.

тут випливає вдосконалена версія:

 /*  removeStorage: removes a key from localStorage and its sibling expiracy key
    params:
        key <string>     : localStorage key to remove
    returns:
        <boolean> : telling if operation succeeded
 */
 function removeStorage(name) {
    try {
        localStorage.removeItem(name);
        localStorage.removeItem(name + '_expiresIn');
    } catch(e) {
        console.log('removeStorage: Error removing key ['+ key + '] from localStorage: ' + JSON.stringify(e) );
        return false;
    }
    return true;
}
/*  getStorage: retrieves a key from localStorage previously set with setStorage().
    params:
        key <string> : localStorage key
    returns:
        <string> : value of localStorage key
        null : in case of expired key or failure
 */
function getStorage(key) {

    var now = Date.now();  //epoch time, lets deal only with integer
    // set expiration for storage
    var expiresIn = localStorage.getItem(key+'_expiresIn');
    if (expiresIn===undefined || expiresIn===null) { expiresIn = 0; }

    if (expiresIn < now) {// Expired
        removeStorage(key);
        return null;
    } else {
        try {
            var value = localStorage.getItem(key);
            return value;
        } catch(e) {
            console.log('getStorage: Error reading key ['+ key + '] from localStorage: ' + JSON.stringify(e) );
            return null;
        }
    }
}
/*  setStorage: writes a key into localStorage setting a expire time
    params:
        key <string>     : localStorage key
        value <string>   : localStorage value
        expires <number> : number of seconds from now to expire the key
    returns:
        <boolean> : telling if operation succeeded
 */
function setStorage(key, value, expires) {

    if (expires===undefined || expires===null) {
        expires = (24*60*60);  // default: seconds for 1 day
    } else {
        expires = Math.abs(expires); //make sure it's positive
    }

    var now = Date.now();  //millisecs since epoch time, lets deal only with integer
    var schedule = now + expires*1000; 
    try {
        localStorage.setItem(key, value);
        localStorage.setItem(key + '_expiresIn', schedule);
    } catch(e) {
        console.log('setStorage: Error setting key ['+ key + '] in localStorage: ' + JSON.stringify(e) );
        return false;
    }
    return true;
}

У setStorage (), чи не повинна бути elseлінія expires = Math.abs(1000*expires); //make sure it's positive?
alissonmuller

Просто точка для getStorageдзвінка. Якщо ви спробуєте отримати доступ до _expiresInверсії ключа безпосередньо, то ключ стає, ..._expiresIn_expiresInякий, звичайно, не існує, тому він видаляє початковий ..._expiresInключ, то наступного разу, коли ви отримаєте доступ до оригінального ключа, його ..._expiresInне існує, і він видаляє оригінал ключ. Я б запропонував захопити це, коли я натрапив на це в одному зі своїх проектів. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
akousmata

24

Хоча локальне зберігання не забезпечує механізм закінчення терміну дії, файли cookie роблять. Просто поєднання локального ключа зберігання з файлом cookie забезпечує простий спосіб забезпечити оновлення локального сховища тими ж параметрами терміну дії, що і cookie.

Приклад у jQuery:

if (!$.cookie('your_key') || !localStorage.getItem('your_key')) {
    //get your_data from server, then...
    localStorage.setItem('your_key', 'your_data' );
    $.cookie('your_key', 1);
} else {
    var your_data = localStorage.getItem('your_key');
}
// do stuff with your_data

Цей приклад встановлює файл cookie з параметром за замовчуванням, який закінчується, коли браузер закритий. Таким чином, коли веб-переглядач закритий та повторно відкритий, локальний сховище даних для ваших_даних оновлюється за допомогою виклику на стороні сервера.

Зауважте, що це не точно так само, як видалення локального сховища даних, це натомість оновлення локального сховища даних кожного разу, коли термін cookie закінчується. Однак, якщо вашою основною метою є можливість зберігати більше 4 Клієнта на стороні клієнта (обмеження розміру файлів cookie), це сполучення файлів cookie та локального сховища допоможе вам досягти більшого розміру пам’яті, використовуючи ті ж параметри закінчення терміну дії, що і cookie .


Файли cookie можна очистити, і, що ще гірше, можна повністю вимкнути.
Верховний Дельфін

1
Мені подобається це рішення найкраще, тому що воно дозволяє браузеру обробляти термін дії нашого сховища без використання інших бібліотек або керування датами локального зберігання вручну.
ecc

10
Майте на увазі, що кукі-файли надсилаються ВСЕ В запиті.
Лукас Фрейтас

24

Тут дуже рекомендується використовувати sessionStorage

  • це те саме, що localStorage, але руйнується, коли сесія знищена / браузер закривається
  • також localStorage може ділитися між вкладками, тоді як sessionStorage може використовуватись лише в поточній вкладці, але значення не змінюється на сторінці оновлення або зміні сторінки
  • sessionStorage також корисний для зменшення мережевого трафіку проти файлів cookie

для використання заданої величини

sessionStorage.setItem("key","my value");

для використання вартості використання

var value = sessionStorage.getItem("key");

натисніть тут, щоб переглянути api

всі способи для набору є

  sessionStorage.key = "my val";
  sessionStorage["key"] = "my val";
  sessionStorage.setItem("key","my value");

всі способи отримати є

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");

8
Зауважте, що sessionStorageне працює для обміну даними між вкладками
Bhargava Mummadireddy

14

Життєвий цикл контролюється додатком / користувачем.

Зі стандартного :

Користувацькі агенти повинні закінчувати термін дії даних з локальних областей зберігання лише з міркувань безпеки або на запит користувача. Користувацькі агенти завжди повинні уникати видалення даних під час виконання сценарію, який може отримати доступ до цих даних.


10

З проекту W3C:

Користувацькі агенти повинні закінчувати термін дії даних з локальних областей зберігання лише з міркувань безпеки або на запит користувача. Користувацькі агенти завжди повинні уникати видалення даних під час виконання сценарію, який може отримати доступ до цих даних.

Ви хочете робити свої оновлення за графіком за допомогою setItem (ключ, значення); який додасть або оновить даний ключ новими даними.


Хм ... можливо, перерахування дати як частини даних було б гарною ідеєю? Або, можливо, використовуючи інший ключ щоразу, коли дані змінюються.
НезадоволенняГота

9
// Functions
function removeHtmlStorage(name) {
    localStorage.removeItem(name);
    localStorage.removeItem(name+'_time');
}

function setHtmlStorage(name, value, expires) {

    if (expires==undefined || expires=='null') { var expires = 3600; } // default: 1h

    var date = new Date();
    var schedule = Math.round((date.setSeconds(date.getSeconds()+expires))/1000);

    localStorage.setItem(name, value);
    localStorage.setItem(name+'_time', schedule);
}

function statusHtmlStorage(name) {

    var date = new Date();
    var current = Math.round(+date/1000);

    // Get Schedule
    var stored_time = localStorage.getItem(name+'_time');
    if (stored_time==undefined || stored_time=='null') { var stored_time = 0; }

    // Expired
    if (stored_time < current) {

        // Remove
        removeHtmlStorage(name);

        return 0;

    } else {

        return 1;
    }
}

// Status
var cache_status = statusHtmlStorage('cache_name');

// Has Data
if (cache_status == 1) {

    // Get Cache
    var data = localStorage.getItem('cache_name');
    alert(data);

// Expired or Empty Cache
} else {

    // Get Data
    var data = 'Pay in cash :)';
    alert(data);

    // Set Cache (30 seconds)
    if (cache) { setHtmlStorage('cache_name', data, 30); }

}

4
Мені подобається такий підхід, оскільки він не вимагає попереднього аналізу даних.
Крістоф

3

Якщо хтось використовує плагін jStorage jQuery, він може додати термін дії з функцією setTTL, якщо плагін jStorage

$.jStorage.set('myLocalVar', "some value");
$.jStorage.setTTL("myLocalVar", 24*60*60*1000); // 24 Hr.

3

Якщо хтось все ще шукає швидкого рішення і не бажає таких залежностей, як jquery і т. Д., Я написав міні-ліб, що додає термін дії до локального / сеансу / спеціального зберігання, ви можете знайти його з джерелом тут:

https://github.com/RonenNess/ExpiredStorage


3

Ви можете спробувати це.

var hours = 24; // Reset when storage is more than 24hours
var now = new Date().getTime();
var setupTime = localStorage.getItem('setupTime');
if (setupTime == null) {
     localStorage.setItem('setupTime', now)
} else {
    if(now-setupTime > hours*60*60*1000) {
         localStorage.clear()
         localStorage.setItem('setupTime', now);
    }
}

1

Вирішення проблем із використанням кутових та місцевих кормів:

angular.module('app').service('cacheService', function() {

  return {
    set: function(key, value, expireTimeInSeconds) {
      return localforage.setItem(key, {
        data: value,
        timestamp: new Date().getTime(),
        expireTimeInMilliseconds: expireTimeInSeconds * 1000
      })
    },
    get: function(key) {
      return localforage.getItem(key).then(function(item) {
        if(!item || new Date().getTime() > (item.timestamp + item.expireTimeInMilliseconds)) {
          return null
        } else {
          return item.data
        }
      })
    }
  }

})

Я перевірив сайт, і я не бачу жодної клавіші "expireTimeInMilliseconds" в їх API. Це недокументований / непідтримуваний параметр?
aaaaaa

1
@PhilOlson - це власна реалізація, яку я використовував localforage. expireTimeInMillisecondsце не якийсь localforageатрибут, а змінна, яку я використовував, щоб перевірити, чи потрібно зберігати дані, що втратили чинність. Перевірте getвизначення функції на моєму прикладі.
Томаш Ромеро

Нічого localforageне легкий клас маленьких помічників, яких я очікував
Simon_Weaver

1

На мою думку, підхід @ sebarmeli є найкращим, але якщо ви хочете, щоб дані зберігалися протягом життя сеансу, то sessionStorage, мабуть, кращий варіант:

Це глобальний об'єкт (sessionStorage), який підтримує область зберігання, доступну протягом тривалості сеансу сторінки. Сеанс сторінки триває до тих пір, поки браузер відкритий і виживає при перезавантаженні та відновленні сторінки. Відкриття сторінки в новій вкладці чи вікні призведе до початку нового сеансу.

MDN: sessionStorage


1

Для вигоди шукачів:

Як і Фернандо, я не хотів додавати json, коли збережені значення були простими. Мені просто потрібно було відстежити деяку взаємодію з інтерфейсом користувача та зберегти відповідні дані (наприклад, як користувач використовував веб-сайт електронної комерції перед тим, як перевірити його).

Це не відповідатиме всім критеріям, але, сподіваємось, це буде швидка копія + вставлення стартера для когось і заощадження додавання ще однієї версії.

ПРИМІТКА. Це не було б добре, якщо вам потрібно отримати елементи окремо.

// Addition
if(window.localStorage){
    localStorage.setItem('myapp-' + new Date().getTime(), 'my value');
}

// Removal of all expired items
if(window.localStorage){

    // two mins - (1000 * 60 * 20) would be 20 mins
    var expiryTime = new Date().getTime() - (1000 * 60 * 2);

    var deleteRows = [];
    for(var i=0; i < localStorage.length; i++){
        var key = localStorage.key(i);
        var partsArray = key.split('-');
        // The last value will be a timestamp
        var lastRow = partsArray[partsArray.length - 1];

        if(lastRow && parseInt(lastRow) < expiryTime){
            deleteRows.push(key);
        }
    }
    // delete old data
    for(var j=0; j < deleteRows.length; j++){
        localStorage.removeItem(deleteRows[j]);
    }
}

0

Якщо ви знайомі з об’єктом locaStorage браузерів , ви знаєте, що не передбачено надання часу закінчення. Однак ми можемо використовувати Javascript, щоб додати TTL (Час жити), щоб визнати недійсними елементи в locaStorage через певний проміжок часу.

function setLocalStorage(key, value, ttl) {
    // `item` is an object which contains the original value
    // as well as the time when it's supposed to expire
    const item = {
        value: value,
        expiry: ttl <= 0 ? -1 : new Date().getTime() + ttl
    };
    localStorage.setItem(key, JSON.stringify(item));
}

function getLocalStorage(key) {
    const itemStr = localStorage.getItem(key);
    // if the item doesn't exist, return null
    if (!itemStr) {
        return null;
    }
    const item = JSON.parse(itemStr);
    // compare the expiry time of the item with the current time
    if (item.expiry > 0 && new Date().getTime() > item.expiry) {
        // If the item is expired, delete the item from storage
        // and return null
        localStorage.removeItem(key);
        return null;
    }
    return item.value;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.