Soluciones de respaldo de almacenamiento local HTML5 [cerrado]

119

Estoy buscando códigos y bibliotecas de JavaScript que puedan simular localStorageen navegadores que no tienen soporte nativo.

Básicamente, me gustaría codificar mi sitio localStoragepara almacenar datos y saber que aún funcionará en navegadores que no lo admitan de forma nativa. Esto significaría que una biblioteca detectaría si window.localStorageexiste y la usaría si existe. Si no existe, entonces crearía algún tipo de método alternativo de almacenamiento local, creando su propia implementación en el window.localStorageespacio de nombres.

Hasta ahora, he encontrado estas soluciones:

  1. Implementación de sessionStorage simple .
  2. Una implementación que utiliza cookies (no está encantada con esta idea).
  3. Dojox.storage de Dojo , pero es algo propio, no una alternativa.

Entiendo que Flash y Silverlight también se pueden usar para almacenamiento local, pero no he encontrado nada sobre su uso como respaldo para HTML5 localStorage estándar. ¿Quizás Google Gears también tiene esta capacidad?

Comparta las bibliotecas, los recursos o los fragmentos de código relacionados que haya encontrado. Estaría especialmente interesado en soluciones basadas en javascript puro o jquery, pero supongo que es poco probable.

Tauren
fuente
sessionStorage y localStorage son parte de la especificación de almacenamiento web ( dev.w3.org/html5/webstorage ). La única diferencia es cuánto tiempo el navegador conservará los datos. Supongo que no encontrará una implementación en la que tenga una pero no la otra (pero no estoy 100% seguro)
rlovtang
1
Vale la pena mencionar que Gears fue oficialmente destituido en febrero pasado; no construiría nada sobre eso.
josh3736
@rlovtang: gracias, soy consciente de la diferencia entre la sesión y el almacenamiento local. Según el artículo de 24ways.org (primer enlace en cuestión, solución n. ° 1), Chrome solo admite localStorage y no sessionStorage. Quizás ese ya no sea el caso, ya que ese artículo fue escrito hace un tiempo.
Tauren
@ josh3736: sí, personalmente me gustaría evitar el uso de cookies y engranajes. Ciertamente no construiría nada que dependa de él, pero si fuera un mecanismo de almacenamiento alternativo para alguien que lo tuviera instalado y no lo codificara directamente, podría usarse.
Tauren
así que en realidad estaba equivocado :) No sabía que Chrome una vez tuvo soporte para localStorage pero no sessionStorage. Chrome tiene soporte para ambos ahora al menos.
rlovtang

Respuestas:

56

Yo uso PersistJS ( repositorio de github ), que maneja el almacenamiento del lado del cliente de manera transparente y sin problemas para su código. Utiliza una única API y obtiene soporte para los siguientes backends:

  • flash: almacenamiento persistente de Flash 8.
  • engranajes: almacenamiento persistente basado en Google Gears.
  • localstorage: almacenamiento de borradores HTML5.
  • whatwg_db: almacenamiento de base de datos en borrador HTML5.
  • globalstorage: almacenamiento de borradores HTML5 (especificación anterior).
  • es decir: comportamientos de datos de usuario de Internet Explorer.
  • cookie: almacenamiento persistente basado en cookies.

Cualquiera de ellos puede desactivarse, si, por ejemplo, no desea utilizar cookies. Con esta biblioteca, obtendrá soporte de almacenamiento nativo del lado del cliente en IE 5.5+, Firefox 2.0+, Safari 3.1+ y Chrome; y soporte asistido por complementos si el navegador tiene Flash o Gears. Si habilita las cookies, funcionará en todo (pero estará limitado a 4 kB).

josh3736
fuente
10
¿PersistJS sigue siendo compatible? Me pregunto cómo se resuelve un problema en el que el navegador se actualiza y el método de almacenamiento elegido cambia (digamos que el almacenamiento local está disponible). ¿La ubicación anterior se vuelve inaccesible?
jcalfee314
2
Al menos parece que ya no está en desarrollo activo.
Mahn
Esta es una biblioteca muy atrevida. Sin ningún conocimiento sobre el tamaño máximo en la mayoría de las tecnologías, deberíamos estar seguros de que nuestra aplicación se ejecuta con mucha suerte ... Además, esto parece ser solo una solución si desea ahorrar <64KB.
dude
@julmot Para eso es una biblioteca. Brinde conveniencia mientras se abstrae de las cosas tediosas. Con suficiente investigación y tiempo, generalmente puede descubrir cómo hacer que funcione, independientemente del tamaño máximo. Por supuesto, parece que el autor de ese proyecto decidió que era demasiado ...
William
¿Sabes si esto funciona con el modo de navegación privada de Safari? Actualmente tengo un problema por el que localStorage no es compatible con Safari Private Browsing tanto en macOS como en iOS.
Austin
61

Polyfill de almacenamiento local simple basado en JS puro:

Demostración: 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
fuente
4
¿¡Por qué esto no está recibiendo reconocimiento !? ¡Gracias hombre!
Robert
4
:) - No me gusta agregar una biblioteca completa para todo lo que necesito.
Aamir Afridi
2
¿Está permitido en JavaScript definir var expireslocalmente y luego al usuario en otro ámbito? en funciónset
happy_marmoset
3
Solo quería señalar que si bien está permitiendo que se establezca una caducidad en la cookie, localStorage nunca caducará. Esto podría causar algunos problemas si está buscando que caduque algo. Puede ser beneficioso agregar una fecha de vencimiento en el almacenamiento local y luego hacer comparaciones de fechas para ver si todavía es aplicable. Por supuesto, también diría que debería usar una cookie si necesita caducidad. Pero creo que este script no debería permitir el vencimiento o permitirlo, para ambos, en lugar de ser inconsistente como lo es actualmente.
Hanna
1
@MohsinSaeed en modo privado, creo que el navegador no te permitirá crear cookies también. superuser.com/questions/589248/…
Aamir Afridi
19

¿Has visto la página de polyfill en el wiki de Modernizr?

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

busque la sección de almacenamiento web en esa página y verá 10 posibles soluciones (a partir de julio de 2011).

¡buena suerte! marca

Mark Lummus
fuente
1
Parece que ninguno de ellos está trabajando en el modo Privado / Incógnito (por ejemplo, Safari o Chrome), ya que su solución es crear cookies, que también está deshabilitado en ese modo.
Alex Klaus
14

A continuación se muestra una versión ordenada de la respuesta de Aamir Afridi que mantiene todo su código encapsulado dentro del alcance local.

Eliminé las referencias que crean una retvariable global y también eliminé el análisis de las cadenas almacenadas "verdaderas" y "falsas" en valores booleanos dentro del BrowserStorage.get()método, lo que podría causar problemas si uno está tratando de almacenar las cadenas "verdaderas" o "falso".

Dado que la API de almacenamiento local solo admite valores de cadena, aún se pueden almacenar / recuperar datos variables de JavaScript junto con sus tipos de datos apropiados codificando dichos datos en una cadena JSON, que luego se puede decodificar utilizando una biblioteca de codificación / decodificación JSON como 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
fuente
10

Personalmente prefiero amplify.js . Me ha funcionado muy bien en el pasado y lo recomendé para todas las necesidades de almacenamiento local.

es compatible con IE 5+, Firefox 2+, Safari 4+, Chrome, Opera 10.5+, iPhone 2+, Android 2+ y proporciona una API consistente para manejar el almacenamiento entre navegadores

raidfive
fuente
3

store.js usa userData e IE y localStorage en otros navegadores.

  • No intenta hacer nada demasiado complejo

  • Sin cookies, sin flash, sin jQuery.

  • API limpia.

  • 5 kb comprimido

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

Mikko Ohtamaa
fuente
1

La silla de jardín también parece ser una buena alternativa

una silla de jardín es como un sofá, excepto que es más pequeña y exterior. perfecto para aplicaciones móviles html5 que necesitan una solución de persistencia ligera, adaptable, simple y elegante.

  • colecciones. una instancia de silla de jardín es en realidad una serie de objetos.
  • persistencia adaptativa. la tienda subyacente se abstrae detrás de una interfaz coherente.
  • comportamiento de colección conectable. a veces necesitamos ayudantes de recopilación, pero no siempre.
j0k
fuente
0

Existe realstorage , que usa Gears como alternativa.

Gaurav
fuente
Gracias. Desafortunadamente, parece que admitiría menos navegadores que la sugerencia de @ josh3736 de PersistJS. Todavía lo echaré un vistazo y agradeceré la sugerencia.
Tauren