Когда истекает срок действия элементов в локальном хранилище HTML5?

338

Как долго доступны данные, хранящиеся в localStorage (как часть DOM Storage в HTML5)? Могу ли я установить срок действия данных, которые я помещаю в localStorage?

user280427
источник
3
не используйте localStorage, если это возможно, потому что срок действия никогда не истекает автоматически, там вы можете использовать sessionStorage, он более предпочтителен
Dharmendrasinh Chudasama

Ответы:

216

Не возможно указать срок действия. Это полностью зависит от пользователя.

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

Конечно, возможно, что что-то, что ваше приложение хранит на клиенте, может не появиться позже. Пользователь может явно избавиться от локального хранилища, или браузер может столкнуться с соображениями пространства. Хорошо программировать в обороне. Как правило, однако, вещи остаются «навсегда», основываясь на некотором практическом определении этого слова.

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

Заостренный
источник
1
Так может ли пользователь рассчитывать на доступность данных, скажем, через год? Может ли разработчик рассчитывать на доступность данных, если пользователь явно не удалит их?
Андрес Риофрио
6
@AndresRiofrio Я не могу найти документацию от Mozilla, Microsoft или W3C, которая предусматривает какой-либо обязательный срок действия. Таким образом, я думаю, что ответ заключается в том, что да, пользовательский агент должен хранить хранимые вещи всегда, или пока пользователь явно не запросит их удаление (или я предполагаю, что ваше собственное приложение не удалит свои собственные вещи).
Заостренный
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
sebarmeli
источник
3
Ну, даже если время клиента не согласовано, вы все равно можете найти способ использовать время сервера. Как эхо-метка времени в div.
Высший Дельфин
Вы бы проанализировали и сравнили временную метку во временном интервале (например, settimoutдля каждых 5 секунд) или для каждого запроса, который клиент отправляет на сервер?
ibubi
лучший способ, чтобы сравнить даты для каждого запроса пользователя
Тераи
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, могут пригодиться, когда вам нужно хранить чрезвычайно временные данные.

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

Brynner Ferreira принесла хорошую мысль: хранить ключ брата, в котором хранится информация об истечении срока действия. Таким образом, если у вас есть большое количество ключей или если ваши значения являются большими объектами 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
25

В то время как локальное хранилище не предоставляет механизм истечения срока действия, куки делают. Простое сопряжение ключа локального хранилища с файлом 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 с параметром по умолчанию, срок действия которого истекает при закрытии браузера. Таким образом, когда браузер закрывается и повторно открывается, локальное хранилище данных для your_data обновляется с помощью вызова на стороне сервера.

Обратите внимание, что это не то же самое, что удаление локального хранилища данных, вместо этого оно обновляет локальное хранилище данных по истечении срока действия файла cookie. Тем не менее, если ваша основная цель состоит в том, чтобы иметь возможность хранить более 4 КБ на стороне клиента (ограничение по размеру файлов cookie), такое сочетание файлов cookie и локального хранилища поможет вам достичь большего размера хранилища, используя те же параметры срока действия, что и файлы cookie. ,

Роберт Пик
источник
Файлы cookie можно очистить и, что еще хуже, можно полностью отключить.
Высший Дельфин
1
Мне больше всего нравится это решение, потому что оно позволяет браузеру справляться с истечением срока действия нашего решения для хранения без необходимости использования других библиотек или управления датами локального хранения вручную.
ecc
10
Имейте в виду, что файлы cookie отправляются в КАЖДОМ запросе.
Лукас Фрейтас
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
15

Жизненный цикл контролируется приложением / пользователем.

Из стандарта :

Пользовательские агенты должны истекать данные из локальных областей хранения только по соображениям безопасности или по запросу пользователя. Пользовательские агенты всегда должны избегать удаления данных во время работы сценария, который может получить доступ к этим данным.

jldupont
источник
11

Из проекта W3C:

Пользовательские агенты должны истекать данные из локальных областей хранения только по соображениям безопасности или по запросу пользователя. Пользовательские агенты всегда должны избегать удаления данных во время работы сценария, который может получить доступ к этим данным.

Вы захотите делать свои обновления в вашем расписании, используя setItem (ключ, значение); это либо добавит, либо обновит данный ключ новыми данными.

FatherStorm
источник
Хм ... может быть, было бы неплохо перечислить дату как часть данных? Или, может быть, каждый раз при изменении данных используется другой ключ.
Рассерженная Стрелка
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.
Amit
источник
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]);
    }
}
HockeyJ
источник
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;
}
iProDev
источник