HTML5本地存储中的项目何时过期?


336

在localStorage(作为HTML5中DOM存储的一部分)中存储的数据可以使用多长时间?我可以为放入localStorage的数据设置过期时间吗?


3
尽可能不要使用localStorage,因为它永远不会自动过期,因此您可以使用sessionStorage更可取
Dharmendrasinh Chudasama

Answers:


215

无法指定到期时间。这完全取决于用户。

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/localStorage

当然,您的应用程序存储在客户端上的某些内容以后可能不会出现。用户可以明确摆脱本地存储,否则浏览器可能会遇到空间问题。进行防御性编程是件好事。但是,一般情况下,根据该单词的一些实际定义,事情将永远保持下去。

编辑 -很明显,如果您认为自己的应用程序过旧,则可以主动删除它们。也就是说,您可以在保存的内容中明确包含某种时间戳,然后在以后使用该时间戳来确定是否应刷新信息。


1
那么,用户可以指望一年后可用的数据吗?除非用户明确删除数据,否则开发人员可以依靠可用的数据吗?
安德烈斯·里奥弗里奥

6
@AndresRiofrio我找不到Mozilla或Microsoft或W3C规定任何强制性到期的任何文档。因此,我认为答案是肯定的,用户代理应该永久保存存储的内容,或者直到用户明确要求将其删除为止(或者我猜直到您自己的应用程序删除其自己的内容为止)。
尖尖的

3
这也意味着您的浏览器不断增长。您曾经使用过一个应用程序,它会将内容存储在浏览器中,并且永远保存在那里....
Pieter van Kampen

1
每个网站可以存储的localStorage数据量约为10mb,但是每个站点平均存储的字符串数不会太多,所以我不介意存储空间
Juan Juan

1
Firefox 在这里有书面的驱逐政策
ShreevatsaR

268

我建议将时间戳存储在您存储在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
好吧,即使客户时间不一致,您仍然可以找到一种使用服务器时间的方法。就像将时间戳回显到div中一样。
至尊海豚

您是否会解析并比较一个时间间隔(例如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结合使用。
Peter Smartt '16

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 '16

只是要点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设置为在关闭浏览器时过期。因此,当浏览器关闭并重新打开时,your_data的本地数据存储将通过服务器端调用进行刷新。

请注意,这与删除本地数据存储并不完全相同,而是在cookie过期时更新本地数据存储。但是,如果您的主要目标是能够存储超过4K的客户端(Cookie大小的限制),则这对Cookie和本地存储的配对将帮助您使用与Cookie相同的到期参数来实现更大的存储大小。


Cookie可以清除,更糟糕的是,可以完全关闭。
至尊海豚

1
我最喜欢此解决方案,因为它使浏览器无需使用其他库或手动管理本地存储日期即可处理我们存储解决方案的到期。
ecc 2016年

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不能在标签之间合作,共享数据
加瓦Mummadireddy

14

生命周期由应用程序/用户控制。

标准

用户代理应仅出于安全原因或在用户要求时才使本地存储区域中的数据过期。用户代理应始终避免在运行可访问该数据的脚本时删除数据。


10

从W3C草案中:

用户代理应仅出于安全原因或在用户要求时才使本地存储区域中的数据过期。用户代理应始终避免在运行可访问该数据的脚本时删除数据。

您将需要使用setItem(key,value);来按计划进行更新。它将使用新数据添加或更新给定密钥。


嗯...也许将日期列为数据的一部分是个好主意吗?或者,每次数据更改时都使用不同的密钥。
DisgruntledGoat 2010年

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
我喜欢这种方法,因为它不需要先解析数据。
Christophe

3

如果有人使用jQuery的jStorage插件,那么如果使用jStorage插件,则可以使用setTTL函数添加到期时间

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


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和localforage的解决方法:

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
        }
      })
    }
  }

})

我检查了该网站,但在他们的API中看不到任何“ expireTimeInMilliseconds”键。它是未记录/不受支持的设置吗?
aaaaaa 2014年

1
@PhilOlson是我使用过的自定义实现localforageexpireTimeInMilliseconds不是某些localforage属性,而是我用来检查存储的数据是否需要过期的变量。get在我的示例中检查函数定义。
Tomas Romero 2014年

哇,localforage这不是我所期待的轻量级小帮手类
Simon_Weaver

1

在我看来,@ sebarmeli的方法是最好的,但是如果您只希望在会话的整个生命周期内都保留数据,那么sessionStorage可能是一个更好的选择:

这是一个全局对象(sessionStorage),用于维护在页面会话期间可用的存储区域。页面会话的持续时间只要浏览器处于打开状态,并且在页面重新加载和还原后仍然存在。在新标签或窗口中打开页面将导致启动新会话。

MDN:sessionStorage


1

为了搜索者的利益:

像Fernando一样,当存储的值很简单时,我不想添加json负载。我只需要跟踪一些UI交互并保持数据相关(例如,用户在结帐前如何使用电子商务网站)。

这将不符合每个人的条件,但是希望可以成为某人的快速复制+粘贴入门程序,并节省添加另一个库的时间。

注意:如果您需要单独检索项目,这将不是很好。

// 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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.