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

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

372775 次浏览

不可能指定过期时间。这完全取决于用户。

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

当然,应用程序存储在客户机上的某些内容以后可能不再存在。用户可以显式地摆脱本地存储,或者浏览器可能会遇到空间问题。防御性的编程是很好的。然而,通常情况下,基于这个词的一些实际定义,事情仍然是“永远”的。

编辑本;显然,如果您自己的应用程序认为某些内容太旧,它可以主动删除这些内容。也就是说,您可以显式地在已保存的内容中包含某种时间戳,然后稍后使用该时间戳来决定是否应该刷新信息。

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

标准:

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

来自W3C草案:

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

你会想要使用setItem(键,值)对你的时间表进行更新;这将使用新数据添加或更新给定的键。

我建议将时间戳存储在localStorage中存储的对象

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

您可以解析对象,获取时间戳并与当前Date进行比较,如果需要,还可以更新对象的值。

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


compareTime(dateString, now); //to implement

另外,你可以使用像localstorage-slim.js .js这样的轻量级包装器来为你处理这个。

你可以使用lscache。它会自动为您处理这个问题,包括存储大小超过限制的实例。如果发生这种情况,它将开始删除最接近指定到期日期的项。

readme:

lscache.set


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


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

这是常规存储方法之间唯一的真正区别。Get、remove等工作原理相同。

如果您不需要那么多的功能,您可以简单地存储一个带有值的时间戳(通过JSON),并检查它是否过期。

值得注意的是,将本地存储留给用户是有充分理由的。但是,当需要存储临时数据时,lscache之类的东西确实会派上用场。

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


}

虽然本地存储不提供过期机制,但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相同的过期参数来实现更大的存储大小。

使用angular和local饲草的解决方案:

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


})

@sebarmeli的方法在我看来是最好的,但如果你只想让数据在一个会话的生命周期内保持,那么sessionStorage可能是一个更好的选择:

这是一个维护存储区域的全局对象(sessionStorage) 在页面会话期间可用。页面会话 只要浏览器打开,就会持续,并在页面上存活 重新加载和恢复。在新选项卡或窗口中打开一个页面会导致

.

.

.

MDN: sessionStorage

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

为了搜索者的利益:

像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]);
}
}

如果有人使用jQuery的jStorage插件,它可以添加过期的setTTL功能,如果jStorage插件

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

这里强烈推荐使用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");

如果有人还在寻找一个快速的解决方案,不想像jquery等依赖,我写了一个迷你库,添加过期到本地/会话/自定义存储,你可以在这里找到它的源代码:

https://github.com/RonenNess/ExpiredStorage

你可以试试这个。

var hours = 24; // Reset when storage is more than 24hours
var now = Date.now();
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);
}

如果你熟悉浏览器locaStorage对象,你就知道没有提供过期时间的规定。但是,我们可以使用Javascript添加一个TTL(生存时间),使locaStorage中的项在一段时间后失效。

function setLocalStorageItem(key, value, ttl) {
// `item` is an object which contains the original value
// as well as the time when it's supposed to expire
let item = {
value: value,
expiry: ttl ? Date.now() + ttl : null
};


localStorage.setItem(key, JSON.stringify(item));
}


function getLocalStorageItem(key) {
let item = localStorage.getItem(key);
    

// if the item doesn't exist, return null
if (!item) return null;


item = JSON.parse(item);
// compare the expiry time of the item with the current time
if (item.expiry && Date.now() > item.expiry) {
// If the item is expired, delete the item from storage and return null
localStorage.removeItem(key);


return null;
}
    

return item.value;
}

Javascript localStorage没有任何设置过期时间的选项

然后我使用这些函数检查支持得到

function ls_support(){
return "localStorage" in window&&window["localStorage"]!==null;
}


function lsset(key,val,exp){
if(ls_support()){
if(!exp) exp=600;// = 10 minutes Default
localStorage[key]=
JSON.stringify({
"val":val,
"exp":~~((new Date()).getTime()/1000)+exp
});
}
}


function lsget(key){
if(ls_support()){
str=localStorage[key];
if("undefined"!=typeof(str)&&str.length){
try{// is json or not
json=JSON.parse(str);
}catch(e){// if variable not set via lsset func
//json.exp=false;// will return null
return str;// will return original variable
}
if(json.exp){// variable setted via lsset func
if(~~((new Date()).getTime()/1000)>json.exp){// expired
delete localStorage[key];
}else{
return json.val;
}
}
}
}
return null;
}

这似乎很有效:

get and set localstorage in pure javascript

function setStorage(name,value){
return localStorage.setItem(name,JSON.stringify({value:value,timestamp:Math.round((new Date()).getTime()/1000)}));
}
function getStorage(name,timeout){
var object = JSON.parse(localStorage.getItem(name));
if(object){
if(Math.round((new Date()).getTime()/1000) < (object.timestamp+timeout)){
return object.value;
}else{
localStorage.removeItem(name);
}
}
return false;
}