Kapan item dalam penyimpanan lokal HTML5 kedaluwarsa?

337

Berapa lama data disimpan di localStorage (sebagai bagian dari DOM Storage di HTML5) tersedia? Bisakah saya menetapkan waktu kedaluwarsa untuk data yang saya masukkan ke localStorage?

pengguna280427
sumber
3
jangan gunakan localStorage jika memungkinkan karena tidak pernah kedaluwarsa secara otomatis, di sana Anda dapat menggunakan sessionStorage itu lebih
disukai

Jawaban:

215

Tidak mungkin menentukan kedaluwarsa. Ini sepenuhnya terserah pengguna.

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

Tentu saja, ada kemungkinan bahwa sesuatu yang disimpan aplikasi Anda pada klien mungkin tidak ada di sana nanti. Pengguna dapat secara eksplisit menyingkirkan penyimpanan lokal, atau browser dapat mengalami pertimbangan ruang. Ini bagus untuk memprogram pertahanan. Namun secara umum hal-hal tetap "selamanya" berdasarkan beberapa definisi praktis dari kata itu.

sunting - jelas, aplikasi Anda sendiri dapat secara aktif menghapus barang-barang jika ia memutuskan sudah terlalu tua. Artinya, Anda dapat secara eksplisit memasukkan semacam stempel waktu dalam apa yang telah Anda simpan, dan kemudian menggunakannya nanti untuk memutuskan apakah informasi harus dibilas atau tidak.

Runcing
sumber
1
Jadi bisakah pengguna mengandalkan data yang tersedia setelah, katakanlah, setahun? Bisakah pengembang mengandalkan data yang tersedia kecuali pengguna menghapusnya secara eksplisit ?
Andres Riofrio
6
@AndresRiofrio Saya tidak dapat menemukan dokumentasi apa pun dari Mozilla atau Microsoft atau W3C yang menetapkan segala jenis kedaluwarsa wajib. Jadi saya pikir jawabannya adalah ya, agen pengguna seharusnya menyimpan barang-barang yang tersimpan selamanya, atau sampai pengguna secara eksplisit meminta itu dihapus (atau saya kira sampai aplikasi Anda sendiri menghapus barang-barangnya sendiri).
Runcing
3
Ini juga berarti peramban Anda terus bertambah. Anda menggunakan aplikasi satu kali, itu menyimpan barang-barang itu di browser Anda, dan itu tetap di sana untuk selamanya ....
Pieter van Kampen
1
Jumlah data Penyimpanan lokal yang dapat Anda simpan per situs web sekitar 10mb, tetapi rata-rata situs tidak akan menyimpan lebih dari beberapa string, jadi saya tidak keberatan dengan ruang penyimpanan
Juan
1
Firefox memiliki kebijakan penggusuran yang terdokumentasi di sini .
ShreevatsaR
269

Saya sarankan untuk menyimpan stempel waktu di objek yang Anda simpan di localStorage

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

Anda dapat mem-parsing objek, mendapatkan cap waktu dan membandingkannya dengan Tanggal saat ini, dan jika perlu, perbarui nilai objek.

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

compareTime(dateString, now); //to implement
sebarmeli
sumber
3
Yah, bahkan jika waktu klien tidak konsisten, Anda masih dapat menemukan cara menggunakan waktu server Anda sebagai gantinya. Seperti menggemakan stempel waktu menjadi sebuah div.
Supreme Dolphin
Apakah Anda akan menguraikan dan membandingkan stempel waktu dalam interval waktu (mis. settimoutUntuk setiap 5 detik) atau untuk setiap permintaan yang dikirim klien ke server?
ibubi
cara yang lebih baik adalah membandingkan tanggal untuk setiap permintaan pengguna
Terai
36

Anda dapat menggunakan lscache . Ini menangani ini untuk Anda secara otomatis, termasuk contoh di mana ukuran penyimpanan melebihi batas. Jika itu terjadi, ia mulai memangkas item yang paling dekat dengan kedaluwarsa yang ditentukan.

Dari readme:

lscache.set

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

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

Ini adalah satu-satunya perbedaan nyata antara metode penyimpanan biasa. Dapatkan, hapus, dll. Pekerjaan yang sama.

Jika Anda tidak membutuhkan fungsionalitas sebanyak itu, Anda cukup menyimpan cap waktu dengan nilai (melalui JSON) dan memeriksanya untuk kedaluwarsa.

Yang perlu diperhatikan, ada alasan bagus mengapa penyimpanan lokal diserahkan kepada pengguna. Tetapi, hal-hal seperti lscache sangat berguna ketika Anda perlu menyimpan data yang sangat sementara.

huyz
sumber
Terima kasih! Ini luar biasa untuk apa yang saya butuhkan - data hanya perlu ada jika pengguna membuat booboo atau browser ditutup sebelum mereka menyimpan pekerjaan mereka, tetapi ada terlalu banyak data untuk cookie. Saya menggunakannya bersamaan dengan pieroxy.net/blog/pages/lz-string/index.html .
Peter Smartt
34

Brynner Ferreira, telah membawa poin bagus: menyimpan kunci saudara di mana info kedaluwarsa berada. Dengan cara ini, jika Anda memiliki sejumlah besar kunci, atau jika nilai Anda adalah objek Json besar , Anda tidak perlu menguraikannya untuk mengakses cap waktu.

di sini mengikuti versi yang ditingkatkan:

 /*  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 Fabreti
sumber
Di setStorage (), bukankah seharusnya elsebaris itu expires = Math.abs(1000*expires); //make sure it's positive?
alissonmuller
Hanya satu poin untuk getStoragepanggilan itu. Jika Anda mencoba mengakses _expiresInversi kunci secara langsung, kunci tersebut menjadi ..._expiresIn_expiresInyang tentu saja tidak ada sehingga menghapus ..._expiresInkunci asli , maka saat berikutnya Anda mengakses kunci asli, yang ..._expiresIntidak ada dan menghapus yang asli kunci. Saya akan menyarankan terperangkap untuk itu ketika saya mengalami ini di salah satu proyek saya. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
akousmata
24

Meskipun penyimpanan lokal tidak menyediakan mekanisme kedaluwarsa, cookie tetap melakukannya. Cukup memasangkan kunci penyimpanan lokal dengan cookie memberikan cara mudah untuk memastikan bahwa penyimpanan lokal dapat diperbarui dengan parameter kedaluwarsa yang sama seperti cookie.

Contoh di 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

Contoh ini menetapkan cookie dengan parameter default untuk kedaluwarsa ketika browser ditutup. Dengan demikian, ketika browser ditutup dan dibuka kembali, penyimpanan data lokal untuk data_Anda disegarkan oleh panggilan sisi server.

Perhatikan bahwa ini tidak persis sama dengan menghapus penyimpanan data lokal, melainkan memperbarui penyimpanan data lokal setiap kali cookie berakhir. Namun, jika tujuan utama Anda adalah untuk dapat menyimpan lebih dari 4K sisi klien (batasan untuk ukuran cookie), pemasangan cookie ini dan penyimpanan lokal akan membantu Anda mencapai ukuran penyimpanan yang lebih besar menggunakan parameter kedaluwarsa yang sama seperti cookie .

Robert Peake
sumber
Cookie dapat dihapus, dan lebih buruk lagi, dapat sepenuhnya dimatikan.
Supreme Dolphin
1
Saya suka solusi ini yang terbaik karena memungkinkan browser menangani kedaluwarsa solusi penyimpanan kami tanpa harus menggunakan perpustakaan lain atau mengelola tanggal penyimpanan lokal secara manual.
ecc
10
Perlu diingat bahwa Cookie dikirim dalam SETIAP permintaan.
Lucas Freitas
24

Di sini sangat disarankan untuk menggunakan sessionStorage

  • itu sama seperti localStorage tetapi hancurkan ketika sesi dihancurkan / browser tutup
  • juga localStorage dapat berbagi di antara tab sementara sessionStorage dapat digunakan hanya di tab saat ini, tetapi nilainya tidak berubah pada halaman refresh atau mengubah halaman
  • sessionStorage juga berguna untuk mengurangi lalu lintas jaringan terhadap cookie

untuk penggunaan nilai yang ditetapkan

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

untuk mendapatkan nilai pakai

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

klik di sini untuk melihat api

semua cara untuk diatur adalah

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

semua cara untuk mendapatkannya adalah

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");
Dharmendrasinh Chudasama
sumber
8
Catatan yang sessionStoragetidak berfungsi untuk berbagi data di antara tab
Bhargava Mummadireddy
14

Siklus hidup dikendalikan oleh aplikasi / pengguna.

Dari standar :

Agen pengguna harus kedaluwarsa data dari area penyimpanan lokal hanya untuk alasan keamanan atau ketika diminta untuk melakukannya oleh pengguna. Agen pengguna harus selalu menghindari menghapus data saat skrip yang dapat mengakses data sedang berjalan.

jldupont
sumber
10

Dari draft W3C:

Agen pengguna harus kedaluwarsa data dari area penyimpanan lokal hanya untuk alasan keamanan atau ketika diminta untuk melakukannya oleh pengguna. Agen pengguna harus selalu menghindari menghapus data saat skrip yang dapat mengakses data sedang berjalan.

Anda akan ingin melakukan pembaruan pada jadwal Anda menggunakan setItem (kunci, nilai); yang akan menambah atau memperbarui kunci yang diberikan dengan data baru.

FatherStorm
sumber
Hmm ... mungkin daftar tanggal sebagai bagian dari data akan menjadi ide yang bagus? Atau mungkin menggunakan kunci berbeda setiap kali data berubah.
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); }

}
Brynner Ferreira
sumber
4
Saya suka pendekatan ini, karena tidak perlu menguraikan data terlebih dahulu.
Christophe
3

Jika seseorang menggunakan Plugin jStorage dari jQuery, itu dapat ditambahkan kadaluwarsa dengan fungsi setTTL jika plugin jStorage

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

Jika ada yang masih mencari solusi cepat dan tidak ingin dependensi seperti jquery dll. Saya menulis lib mini yang menambahkan kedaluwarsa pada penyimpanan lokal / session / custom, Anda dapat menemukannya dengan sumber di sini:

https://github.com/RonenNess/ExpiredStorage

Ronen Ness
sumber
3

Anda bisa coba yang ini.

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);
    }
}
Jay Chauhan
sumber
1

Penanganan masalah menggunakan sudut dan lokal:

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

})
Tomas Romero
sumber
Saya memeriksa situs tersebut, dan saya tidak melihat kunci 'expireTimeInMilliseconds' di API mereka. Apakah ini pengaturan tidak berdokumen / tidak didukung?
aaaaaa
1
@ PhilOlson itu implementasi khusus yang saya gunakan localforage. expireTimeInMillisecondsbukan localforageatribut, tetapi variabel yang saya gunakan untuk memeriksa apakah data yang disimpan perlu kedaluwarsa. Periksa getdefinisi fungsi pada contoh saya.
Tomas Romero
wow localforagebukan kelas pembantu kecil ringan yang kuharapkan
Simon_Weaver
1

@ Sebarmeli's pendekatan adalah yang terbaik menurut saya, tetapi jika Anda hanya ingin data bertahan selama sesi maka sessionStoragemungkin pilihan yang lebih baik:

Ini adalah objek global (sessionStorage) yang mempertahankan area penyimpanan yang tersedia selama sesi halaman. Sesi halaman berlangsung selama browser terbuka dan bertahan selama pemuatan dan pemulihan halaman. Membuka halaman di tab atau jendela baru akan menyebabkan sesi baru dimulai.

MDN: sessionStorage

Kevin Leary
sumber
1

Untuk kepentingan pencari:

Seperti Fernando, saya tidak ingin menambahkan beban json ketika nilai yang disimpan sederhana. Saya hanya perlu melacak beberapa interaksi UI dan menyimpan data yang relevan (misalnya bagaimana pengguna menggunakan situs e-niaga sebelum memeriksa).

Ini tidak akan memenuhi kriteria everyones, tetapi mudah-mudahan akan menjadi copy cepat + tempel starter untuk seseorang dan menyimpan menambahkan lib lain

CATATAN: Ini tidak baik jika Anda perlu mengambil item satu per satu.

// 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]);
    }
}
Hoki
sumber
0

Jika Anda terbiasa dengan objek locaStorage browser , Anda tahu bahwa tidak ada ketentuan untuk memberikan waktu kedaluwarsa. Namun, kita dapat menggunakan Javascript untuk menambahkan TTL (Time to live) untuk membatalkan item di locaStorage setelah periode waktu tertentu berlalu.

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
sumber