รายการในที่จัดเก็บในตัว HTML5 หมดอายุเมื่อใด


337

มีการจัดเก็บข้อมูลใน localStorage นานเท่าใด (ซึ่งเป็นส่วนหนึ่งของ DOM Storage ใน HTML5) ฉันสามารถกำหนดเวลาหมดอายุสำหรับข้อมูลที่ฉันใส่ลงใน localStorage ได้หรือไม่?


3
ไม่ได้ใช้localStorageถ้าเป็นไปได้คือเพราะไม่มีวันหมดอายุโดยอัตโนมัติมีคุณสามารถใช้sessionStorageมันเป็น preferrable เพิ่มเติม
Dharmendrasinh Chudasama

คำตอบ:


215

ไม่สามารถระบุการหมดอายุได้ มันขึ้นอยู่กับผู้ใช้อย่างสมบูรณ์

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

แน่นอนเป็นไปได้ว่ามีบางสิ่งที่แอปพลิเคชันของคุณเก็บไว้ในไคลเอนต์อาจไม่มีอยู่ในภายหลัง ผู้ใช้สามารถกำจัดที่จัดเก็บในตัวเครื่องอย่างชัดเจนหรือเบราว์เซอร์อาจมีการพิจารณาเรื่องพื้นที่ มันเป็นการดีที่จะตั้งโปรแกรมป้องกัน โดยทั่วไปอย่างไรก็ตามสิ่งต่าง ๆ ยังคง "ตลอดไป" ตามคำจำกัดความของคำนั้น

แก้ไข - เห็นได้ชัดว่าแอปพลิเคชันของคุณสามารถลบสิ่งต่าง ๆ ได้อย่างแข็งขันหากมันตัดสินว่ามันเก่าเกินไป นั่นคือคุณสามารถรวมการประทับเวลาบางอย่างไว้ในสิ่งที่คุณได้รับการบันทึกแล้วใช้ในภายหลังเพื่อตัดสินใจว่าควรล้างข้อมูลหรือไม่


1
ดังนั้นผู้ใช้สามารถนับจำนวนข้อมูลที่มีอยู่หลังจากหนึ่งปีได้หรือไม่? นักพัฒนาสามารถนับจำนวนข้อมูลที่มีอยู่ได้หรือไม่เว้นแต่ผู้ใช้จะลบอย่างชัดเจน ?
Andres Riofrio

6
@AndresRiofrio ฉันไม่พบเอกสารใด ๆ จาก Mozilla หรือ Microsoft หรือ W3C ที่กำหนดประเภทการหมดอายุที่บังคับ ดังนั้นฉันคิดว่าคำตอบคือใช่ตัวแทนผู้ใช้ควรเก็บสิ่งที่เก็บไว้ตลอดไปหรือจนกว่าผู้ใช้จะร้องขออย่างชัดเจนว่าจะถูกลบออก (หรือฉันเดาว่าจนกว่าแอปพลิเคชันของคุณจะลบเนื้อหาของตัวเอง)
Pointy

3
นี่หมายถึงเบราว์เซอร์ของคุณเติบโตขึ้นเรื่อย ๆ คุณใช้แอปหนึ่งครั้งมันเก็บของไว้ในเบราว์เซอร์และมันจะอยู่ที่นั่นตลอดไป ....
Pieter van Kampen

1
จำนวนข้อมูล localStorage ที่คุณสามารถจัดเก็บได้ต่อเว็บไซต์อยู่ที่ประมาณ 10mb แต่ไซต์เฉลี่ยจะไม่เก็บมากกว่าสองสามสตริงดังนั้นฉันจะไม่คำนึงถึงพื้นที่เก็บข้อมูล
Juan

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
แม้ว่าเวลาไคลเอ็นต์จะไม่สอดคล้องกันคุณยังสามารถหาวิธีใช้เวลาเซิร์ฟเวอร์ของคุณแทนได้ เช่นเดียวกับการสะท้อนการประทับเวลาเป็น div
Supreme Dolphin

คุณจะแยกวิเคราะห์และเปรียบเทียบการประทับเวลาในช่วงเวลา (เช่น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 มีประโยชน์เมื่อคุณต้องการจัดเก็บข้อมูลชั่วคราวมาก


ขอบคุณ! นี่เป็นสิ่งที่ยอดเยี่ยมสำหรับสิ่งที่ฉันต้องการ - ข้อมูลจะต้องอยู่ที่นั่นในกรณีที่ผู้ใช้ทำบูบูหรือเบราว์เซอร์ถูกปิดก่อนที่พวกเขาจะบันทึกงานของพวกเขา แต่มีข้อมูลคุกกี้มากเกินไป ฉันใช้มันร่วมกับpieroxy.net/blog/pages/lz-string/index.html
Peter Smartt

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

24

แม้ว่าที่เก็บข้อมูลในเครื่องจะไม่จัดหากลไกการหมดอายุคุกกี้ก็ทำเช่นกัน เพียงจับคู่คีย์หน่วยเก็บข้อมูลโลคัลกับคุกกี้เป็นวิธีที่ง่ายเพื่อให้แน่ใจว่าพื้นที่เก็บข้อมูลโลคัลสามารถอัพเดตได้ด้วยพารามิเตอร์การหมดอายุเช่นเดียวกับคุกกี้

ตัวอย่างใน 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

ตัวอย่างนี้ตั้งค่าคุกกี้พร้อมพารามิเตอร์เริ่มต้นให้หมดอายุเมื่อปิดเบราว์เซอร์ ดังนั้นเมื่อเบราว์เซอร์ปิดและเปิดใหม่ที่เก็บข้อมูลในเครื่องสำหรับ your_data จะได้รับการรีเฟรชโดยการโทรฝั่งเซิร์ฟเวอร์

โปรดทราบว่านี่ไม่เหมือนกับการลบที่เก็บข้อมูลโลคัล แต่เป็นการอัพเดตที่เก็บข้อมูลโลคัลแทนเมื่อใดก็ตามที่คุกกี้หมดอายุ อย่างไรก็ตามหากเป้าหมายหลักของคุณคือเพื่อให้สามารถจัดเก็บมากกว่าฝั่งไคลเอ็นต์ 4K (ข้อ จำกัด สำหรับขนาดคุกกี้) การจับคู่คุกกี้และที่จัดเก็บในตัวเครื่องนี้จะช่วยให้คุณบรรลุขนาดพื้นที่เก็บข้อมูลขนาดใหญ่ขึ้นโดยใช้พารามิเตอร์การหมดอายุเช่นเดียวกับคุกกี้ .


สามารถล้างคุกกี้และยังสามารถปิดได้โดยสิ้นเชิง
Supreme Dolphin

1
ฉันชอบโซลูชันนี้ที่สุดเพราะช่วยให้เบราว์เซอร์จัดการการหมดอายุของโซลูชันหน่วยเก็บข้อมูลของเราโดยไม่ต้องใช้ไลบรารีอื่นหรือจัดการวันที่เก็บข้อมูลในเครื่องด้วยตนเอง
ecc

10
โปรดทราบว่ามีการส่งคุกกี้ทุกคำขอ
Lucas Freitas

24

ขอแนะนำให้ใช้sessionStorage

  • มันเหมือนกับlocalStorageแต่ทำลายเมื่อเซสชั่นถูกทำลาย / ปิดเบราว์เซอร์
  • localStorageยังสามารถแชร์ระหว่างแท็บในขณะที่sessionStorageสามารถใช้ในแท็บปัจจุบันเท่านั้น แต่ค่าจะไม่เปลี่ยนแปลงในหน้ารีเฟรชหรือเปลี่ยนหน้า
  • sessionStorage ยังมีประโยชน์ในการลดทราฟฟิกเครือข่ายกับคุกกี้

สำหรับการตั้งค่าการใช้งาน

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 (คีย์, ค่า); ที่จะเพิ่มหรืออัปเดตคีย์ที่กำหนดด้วยข้อมูลใหม่


อืม ... การระบุวันที่เป็นส่วนหนึ่งของข้อมูลอาจเป็นความคิดที่ดีใช่ไหม หรืออาจใช้รหัสที่แตกต่างกันในแต่ละครั้งที่ข้อมูลมีการเปลี่ยนแปลง
DisgruntledGoat

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

หากใครบางคนที่ใช้ปลั๊กอิน jStorage ของ jQuery มันสามารถเพิ่มการหมดอายุด้วยฟังก์ชั่น setTTL ถ้าปลั๊กอิน jStorage

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

3

หากใครยังคงมองหาวิธีการแก้ปัญหาอย่างรวดเร็วและไม่ต้องการการพึ่งพาเช่น jQuery ฯลฯ ฉันเขียน lib ขนาดเล็กที่เพิ่มการหมดอายุลงในที่จัดเก็บในพื้นที่ / เซสชัน / กำหนดเองคุณสามารถค้นหาได้จากแหล่งที่นี่:

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

วิธีแก้ปัญหาโดยใช้มุมและ 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
        }
      })
    }
  }

})

ฉันตรวจสอบไซต์แล้วและไม่เห็นคีย์ 'expireTimeInMilliseconds' ใน API ของพวกเขา เป็นการตั้งค่าที่ไม่มีเอกสาร / ไม่สนับสนุนหรือไม่
aaaaaa

1
@PhilOlson localforageที่ดำเนินการเองผมเคยใช้ใช้ expireTimeInMillisecondsไม่ใช่localforageคุณลักษณะบางอย่างแต่เป็นตัวแปรที่ฉันเคยตรวจสอบว่าข้อมูลที่เก็บไว้นั้นต้องหมดอายุหรือไม่ ตรวจสอบgetนิยามฟังก์ชั่นในตัวอย่างของฉัน
Tomas Romero

ว้าวlocalforageไม่ใช่ชั้นผู้ช่วยตัวเล็กที่มีน้ำหนักเบาอย่างที่ฉันคาดหวัง
Simon_Weaver

1

วิธีการของ @ sebarmeli นั้นดีที่สุดในความคิดของฉัน แต่ถ้าคุณต้องการให้ข้อมูลคงอยู่ตลอดชีวิตของเซสชั่นsessionStorageคงเป็นตัวเลือกที่ดีกว่า:

นี่เป็นวัตถุส่วนกลาง (sessionStorage) ที่ดูแลพื้นที่จัดเก็บที่พร้อมใช้งานสำหรับช่วงเวลาของเซสชันหน้า เซสชั่นหน้าเป็นเวลาตราบเท่าที่เบราว์เซอร์ที่เปิดอยู่และมีชีวิตอยู่เหนือการโหลดหน้าเว็บและเรียกคืน การเปิดหน้าเว็บในแท็บหรือหน้าต่างใหม่จะทำให้เซสชันใหม่เริ่มต้น

MDN: sessionStorage


1

เพื่อประโยชน์ของผู้ค้นหา:

เช่นเดียวกับ Fernando ฉันไม่ต้องการเพิ่มโหลดของ json เมื่อค่าที่เก็บไว้นั้นเรียบง่าย ฉันต้องการติดตามการโต้ตอบ UI และเก็บข้อมูลที่เกี่ยวข้อง (เช่นวิธีที่ผู้ใช้ใช้ไซต์อีคอมเมิร์ซก่อนเช็คเอาต์)

สิ่งนี้จะไม่เป็นไปตามเกณฑ์ของทุกคน แต่หวังว่าจะเป็นตัวคัดลอก + เริ่มต้นอย่างรวดเร็วสำหรับบางคนและบันทึกการเพิ่ม lib อื่น

หมายเหตุ: สิ่งนี้จะไม่ดีถ้าคุณต้องการดึงรายการแยกต่างหาก

// 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.