Solusi fallback Penyimpanan Lokal HTML5 [ditutup]

119

Saya mencari pustaka dan kode javascript yang dapat disimulasikan localStoragepada browser yang tidak memiliki dukungan asli.

Pada dasarnya, saya ingin membuat kode pada situs saya localStorageuntuk menyimpan data dan mengetahui bahwa itu masih akan berfungsi di browser yang tidak mendukungnya secara native. Ini berarti perpustakaan akan mendeteksi jika window.localStorageada dan menggunakannya jika memang ada. Jika tidak ada, maka itu akan membuat semacam metode fallback penyimpanan lokal, dengan membuat implementasinya sendiri di window.localStoragenamespace.

Sejauh ini, saya telah menemukan solusi ini:

  1. Penerapan sessionStorage sederhana .
  2. Penerapan yang menggunakan cookie (tidak senang dengan ide ini).
  3. Dojo's dojox.storage , tapi itu milik sendiri, bukan benar-benar mundur.

Saya memahami bahwa Flash dan Silverlight juga dapat digunakan untuk penyimpanan lokal, tetapi belum menemukan apa pun tentang penggunaannya sebagai pengganti untuk penyimpanan lokal HTML5 standar. Mungkinkah Google Gears memiliki kemampuan ini juga?

Bagikan pustaka, sumber daya, atau cuplikan kode terkait yang Anda temukan! Saya akan sangat tertarik pada solusi berbasis javascript atau jquery murni, tetapi saya menebak itu tidak mungkin.

Tauren
sumber
sessionStorage dan localStorage adalah bagian dari spesifikasi Penyimpanan Web ( dev.w3.org/html5/webstorage ). Satu-satunya perbedaan adalah berapa lama browser akan menyimpan data. Saya kira Anda tidak akan menemukan implementasi di mana Anda memilikinya tetapi tidak yang lain (tapi saya tidak 100% yakin)
rlovtang
1
Perlu disebutkan bahwa Gears secara resmi dikosongkan Februari lalu - saya tidak akan membuat apa pun di atasnya.
josh3736
@rlovtang: terima kasih, saya mengetahui perbedaan antara sesi dan penyimpanan lokal. Menurut artikel 24ways.org (tautan pertama yang dipermasalahkan, solusi # 1), Chrome hanya mendukung localStorage dan bukan sessionStorage. Mungkin bukan itu masalahnya lagi, karena artikel itu ditulis beberapa waktu yang lalu.
Tauren
@ josh3736: ya, saya pribadi ingin menghindari penggunaan cookie dan roda gigi. Saya pasti tidak akan membangun apa pun yang bergantung padanya, tetapi jika itu adalah mekanisme penyimpanan cadangan untuk seseorang yang telah menginstalnya, dan saya tidak mengkodekannya secara langsung, itu dapat digunakan.
Tauren
jadi saya sebenarnya salah :) Tidak tahu Chrome pernah memiliki dukungan untuk localStorage tetapi tidak sessionStorage. Chrome memiliki dukungan setidaknya untuk keduanya sekarang.
rlovtang

Jawaban:

56

Saya menggunakan PersistJS ( github repository ), yang menangani penyimpanan sisi klien secara mulus dan transparan ke kode Anda. Anda menggunakan satu API dan mendapatkan dukungan untuk backend berikut:

  • flash: Penyimpanan persisten Flash 8.
  • gears: Penyimpanan persisten berbasis Google Gears.
  • penyimpanan lokal: penyimpanan draf HTML5.
  • whatwg_db: penyimpanan database draf HTML5.
  • globalstorage: penyimpanan draf HTML5 (spesifikasi lama).
  • yaitu: perilaku data pengguna Internet Explorer.
  • cookie: Penyimpanan persisten berbasis cookie.

Semua itu dapat dinonaktifkan — jika, misalnya, Anda tidak ingin menggunakan cookie. Dengan pustaka ini, Anda akan mendapatkan dukungan penyimpanan sisi klien asli di IE 5.5+, Firefox 2.0+, Safari 3.1+, dan Chrome; dan dukungan bantuan plugin jika browser memiliki Flash atau Gears. Jika Anda mengaktifkan cookie, cookie akan berfungsi di segala hal (tetapi akan dibatasi hingga 4 kB).

josh3736
sumber
10
Apakah PersistJS masih didukung? Saya bertanya-tanya bagaimana ini memecahkan masalah di mana browser ditingkatkan dan metode penyimpanan yang dipilih berubah (katakanlah penyimpanan lokal menjadi tersedia). Apakah lokasi lama menjadi tidak dapat diakses?
jcalfee314
2
Setidaknya itu tidak terlihat seperti dalam pengembangan aktif lagi.
Mahn
Ini adalah perpustakaan yang sangat berani. Tanpa pengetahuan tentang ukuran maksimal di sebagian besar teknologi, kami harus yakin bahwa aplikasi kami berjalan dengan banyak keberuntungan ... Juga ini tampaknya hanya solusi jika Anda ingin menghemat <64KB.
Bung
@julmot Itulah gunanya perpustakaan. Berikan kemudahan sambil mengabstraksi hal-hal yang membosankan. Dengan penelitian dan waktu yang cukup, Anda biasanya dapat mengetahui cara membuatnya bekerja, terlepas dari ukuran maksimalnya. Tentu saja, sepertinya pembuat proyek itu memutuskan itu terlalu berlebihan ...
William
Tahukah Anda jika ini berfungsi dengan mode Penjelajahan Pribadi Safari? Saat ini saya mengalami masalah di mana penyimpanan lokal tidak didukung di Safari Private Browsing baik macOS maupun iOS.
Austin
61

Polyfill localStorage sederhana berbasis JS:

Demo: http://jsfiddle.net/aamir/S4X35/

HTML:

<a href='#' onclick="store.set('foo','bar')">set key: foo, with value: bar</a><br/>
<a href='#' onclick="alert(store.get('foo'))">get key: foo</a><br/>
<a href='#' onclick="store.del('foo')">delete key: foo</a>​

JS:

window.store = {
    localStoreSupport: function() {
        try {
            return 'localStorage' in window && window['localStorage'] !== null;
        } catch (e) {
            return false;
        }
    },
    set: function(name,value,days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else {
            var expires = "";
        }
        if( this.localStoreSupport() ) {
            localStorage.setItem(name, value);
        }
        else {
            document.cookie = name+"="+value+expires+"; path=/";
        }
    },
    get: function(name) {
        if( this.localStoreSupport() ) {
            var ret = localStorage.getItem(name);
            //console.log(typeof ret);
            switch (ret) {
              case 'true': 
                  return true;
              case 'false':
                  return false;
              default:
                  return ret;
            }
        }
        else {
            // cookie fallback
            /*
             * after adding a cookie like
             * >> document.cookie = "bar=test; expires=Thu, 14 Jun 2018 13:05:38 GMT; path=/"
             * the value of document.cookie may look like
             * >> "foo=value; bar=test"
             */
            var nameEQ = name + "=";  // what we are looking for
            var ca = document.cookie.split(';');  // split into separate cookies
            for(var i=0;i < ca.length;i++) {
                var c = ca[i];  // the current cookie
                while (c.charAt(0)==' ') c = c.substring(1,c.length);  // remove leading spaces
                if (c.indexOf(nameEQ) == 0) {  // if it is the searched cookie
                    var ret = c.substring(nameEQ.length,c.length);
                    // making "true" and "false" a boolean again.
                    switch (ret) {
                      case 'true':
                          return true;
                      case 'false':
                          return false;
                      default:
                          return ret;
                    }
                }
            }
            return null; // no cookie found
        }
    },
    del: function(name) {
        if( this.localStoreSupport() ) {
            localStorage.removeItem(name);
        }
        else {
            this.set(name,"",-1);
        }
    }
}​
Aamir Afridi
sumber
4
Kenapa ini tidak mendapatkan pengakuan !? Terima kasih sobat!
Robert
4
:) - Saya tidak suka menambahkan seluruh lib untuk semua yang saya butuhkan.
Aamir Afridi
2
apakah diperbolehkan dalam JavaScript untuk mendefinisikan var expiressecara lokal dan kemudian pengguna dalam lingkup lain? dalam fungsiset
happy_marmoset
3
Hanya ingin menunjukkan bahwa saat Anda mengizinkan kadaluwarsa untuk ditetapkan pada cookie, penyimpanan lokal tidak akan pernah kedaluwarsa. Ini dapat menyebabkan beberapa masalah jika Anda mencari sesuatu yang kedaluwarsa. Mungkin bermanfaat untuk memasukkan menambahkan tanggal kedaluwarsa di penyimpanan lokal dan kemudian membuat perbandingan tanggal untuk melihat apakah itu masih berlaku. Tentu saja saya juga berpendapat bahwa Anda sebaiknya menggunakan cookie jika Anda membutuhkan kedaluwarsa. Tapi saya pikir skrip ini seharusnya tidak mengizinkan kedaluwarsa atau mengizinkannya, untuk keduanya, daripada menjadi tidak konsisten seperti saat ini.
Hanna
1
@MohsinSaeed dalam mode pribadi, menurut saya browser tidak akan mengizinkan Anda membuat cookie juga. superuser.com/questions/589248/…
Aamir Afridi
19

pernahkah Anda melihat halaman polyfill di Modernizr wiki?

https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills

cari bagian penyimpanan web di halaman itu dan Anda akan melihat 10 solusi potensial (per Juli 2011).

semoga berhasil! Menandai

Mark Lummus
sumber
1
Tampaknya tidak ada satupun yang berfungsi dalam mode Pribadi / Penyamaran (mis. Safari atau Chrome), karena solusi mereka adalah membuat cookie, yang juga dinonaktifkan dalam mode itu.
Alex Klaus
14

Di bawah ini adalah versi rapih dari tanggapan Aamir Afridi yang menyimpan semua kodenya dienkapsulasi dalam lingkup lokal.

Saya telah menghapus referensi yang membuat retvariabel global dan juga menghapus penguraian string "true" dan "false" yang disimpan ke dalam nilai boolean dalam BrowserStorage.get()metode, yang dapat menyebabkan masalah jika seseorang mencoba untuk menyimpan string "true" atau "Salah".

Karena API penyimpanan lokal hanya mendukung nilai string, seseorang masih dapat menyimpan / mengambil data variabel JavaScript bersama dengan tipe datanya yang sesuai dengan mengenkode data tersebut ke dalam string JSON, yang kemudian dapat didekodekan menggunakan pustaka encode / decode JSON seperti https: //github.com/douglascrockford/JSON-js

var BrowserStorage = (function() {
    /**
     * Whether the current browser supports local storage as a way of storing data
     * @var {Boolean}
     */
    var _hasLocalStorageSupport = (function() {
        try {
            return 'localStorage' in window && window['localStorage'] !== null;
        } catch (e) {
            return false;
        }
    })();

    /**
     * @param {String} name The name of the property to read from this document's cookies
     * @return {?String} The specified cookie property's value (or null if it has not been set)
     */
    var _readCookie = function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }

        return null;
    };

    /**
     * @param {String} name The name of the property to set by writing to a cookie
     * @param {String} value The value to use when setting the specified property
     * @param {int} [days] The number of days until the storage of this item expires
     */
    var _writeCookie = function(name, value, days) {
        var expiration = (function() {
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days*24*60*60*1000));
                return "; expires=" + date.toGMTString();
            }
            else {
                return "";
            }
        })();

        document.cookie = name + "=" + value + expiration + "; path=/";
    };

    return {
        /**
         * @param {String} name The name of the property to set
         * @param {String} value The value to use when setting the specified property
         * @param {int} [days] The number of days until the storage of this item expires (if storage of the provided item must fallback to using cookies)
         */
        set: function(name, value, days) {
            _hasLocalStorageSupport
                ? localStorage.setItem(name, value)
                : _writeCookie(name, value, days);
        },

        /**
         * @param {String} name The name of the value to retrieve
         * @return {?String} The value of the 
         */
        get: function(name) {
            return _hasLocalStorageSupport
                ? localStorage.getItem(name) 
                : _readCookie(name);
        },

        /**
         * @param {String} name The name of the value to delete/remove from storage
         */
        remove: function(name) {
            _hasLocalStorageSupport
                ? localStorage.removeItem(name)
                : this.set(name, "", -1);
        }
    };
})();
Steven
sumber
10

Saya pribadi lebih suka amplify.js . Ini telah bekerja sangat baik untuk saya di masa lalu dan saya merekomendasikannya untuk semua kebutuhan penyimpanan lokal.

mendukung IE 5+, Firefox 2+, Safari 4+, Chrome, Opera 10.5+, iPhone 2+, Android 2+ dan menyediakan API yang konsisten untuk menangani penyimpanan lintas browser

raidfive
sumber
3

store.js menggunakan userData dan IE dan localStorage di browser lain.

  • Ia tidak mencoba melakukan sesuatu yang terlalu rumit

  • Tanpa cookie, tidak ada flash, tidak perlu jQuery.

  • API bersih.

  • 5 kb terkompresi

https://github.com/marcuswestin/store.js

Mikko Ohtamaa
sumber
1

Lawnchair tampaknya juga menjadi alternatif yang bagus

kursi taman agak seperti sofa kecuali lebih kecil dan di luar. sempurna untuk aplikasi seluler html5 yang membutuhkan solusi ketekunan yang ringan, adaptif, sederhana, dan elegan.

  • koleksi. contoh kursi taman benar-benar hanya serangkaian objek.
  • ketekunan adaptif. penyimpanan yang mendasarinya diabstraksi di balik antarmuka yang konsisten.
  • perilaku pengumpulan yang dapat dicolokkan. terkadang kami membutuhkan pembantu koleksi tetapi tidak selalu.
j0k
sumber
0

Ada penyimpanan nyata , yang menggunakan Gears sebagai cadangan.

Gaurav
sumber
Terima kasih. Sayangnya, sepertinya itu akan mendukung lebih sedikit browser daripada saran @ josh3736 dari PersistJS. Saya masih akan melihatnya, dan menghargai sarannya.
Tauren