Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

10 years ago by FelipeBudinich

I've been refining a Persistence module to use with my games for quite some time, and I've decided to share it.

It's very simple to use, you only need to require the module then:
// To set a variable
ig.persistence.set('key', 'value');

// To get a variable
var myVariable = ig.persistence.get('key');

// To get a variable, or a default value if not set previously
var myVariable = ig.persistence.get('key', 'default value');

// To get a float number
var volume = ig.persistence.getFloat("volume");

// To get a float number, and if the key is not set, use a default value of 0.5
var volume = ig.persistence.getFloat("volume", 0.5);

You can get the code below, or from this gist
/*global ig*/
ig.module(
    'plugins.persistence'
).requires(
    'impact.game'
).defines(function () {
    'use strict';
    ig.PersistenceError = function (message) {
        this.name = "PersistenceError";
        this.message = message;
    };
    ig.PersistenceError.prototype = Error.prototype;
    ig.PersistenceManager = ig.Class.extend({
        staticInstantiate: function (i) {
            return ig.PersistenceManager.instance || null;
        },
        alias: function (name) {
            Object.defineProperty(ig, name, {
                value: this,
                writable: false,
                enumerable: true,
                configurable: false
            });
        },
        init: function () {
            try {
                if (window.localStorage) {
                    ig.PersistenceManager.instance = this;
                    this.alias('persistence');
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of local storage.");
            }
        },
        isSet: function (key) {
            return (this.get(key) !== 'undefined');
        },
        get: function (key, defaultValue) {
            var value = localStorage.getItem(key);
            if (value !== null) {
                if (value !== 'undefined') {
                    value = JSON.parse(value);
                    return value;
                } else {
                    throw new ig.PersistenceError("The value stored for " + "'" + key + "'" + " is undefined.");
                }
            } else if (typeof defaultValue !== 'undefined') {
                return defaultValue;
            } else {
                throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
            }
        },
        getInt: function (key, defaultValue) {
            return parseInt(this.get(key, defaultValue), null);
        },
        getFloat: function (key, defaultValue) {
            return parseFloat(this.get(key, defaultValue));
        },
        getBool: function (key, defaultValue) {
            var value = this.get(key, defaultValue);
            switch (value.toLowerCase()) {
            case 'true':
                return true;
            case 'false':
                return false;
            default:
                throw new ig.PersistenceError("Value set for " + "'" + key + "'" + " is not boolean.");
            }
        },
        set: function (key, value) {
            window.localStorage.setItem(key, JSON.stringify(value));
        },
        setHigher: function (key, value) {
            if (value > this.getFloat(key)) {
                this.set(key, value);
            }
        },
        setLower: function (key, value) {
            if (value < this.getFloat(key)) {
                this.set(key, value);
            }
        },
        remove: function (key) {
            if (this.isSet(key)) {
                window.localStorage.removeItem(key);
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        },
        clear: function () {
            window.localStorage.clear();
        }
    });
    return new ig.PersistenceManager();
});

10 years ago by FelipeBudinich

I just updated my persistence plugin to allow the use of a different solution depeding on user configuration, inspired by a snippet from Game Programming Patterns:
FileSystem& FileSystem::instance()
{
#if PLATFORM == PLAYSTATION3
static FileSystem *instance = new PS3FileSystem();
#elif PLATFORM == WII
static FileSystem *instance = new WiiFileSystem();
#endif

return *instance;
}

/*global ig*/
ig.module(
    'plugins.persistence'
).requires(
    'impact.game'
).defines(function () {
    'use strict';
    ig.PersistenceError = function (message) {
        this.name = "PersistenceError";
        this.message = message;
    };
    ig.PersistenceError.prototype = Error.prototype;
    ig.Persistence = ig.Class.extend({
        /**
         * Create a static instance of this class
         */
        staticInstantiate: function (i) {
            this.alias('persistence');
            // for demostration purposes I'll create a ig.config object that contains the configuration we will be using
            // to select between two different implementations
            ig.config = {};
            ig.config.persistOn = 'localStorage';
            switch (ig.config.persistOn) {
            case 'localStorage':
                ig.Persistence.inject(ig.Persistence.LocalStorage.prototype);
                break;
            case 'otherFileSystem':
                ig.Persistence.inject(ig.Persistence.OtherFileSystem.prototype);
                break;
            default:
                throw new ig.PersistenceError("No persistence enviroment defined.");
            }
            return ig.Persistence.instance || null;
        },
        /**
         * Sets an alias that can be used to access this singleton
         */
        alias: function (name) {
            Object.defineProperty(ig, name, {
                value: this,
                writable: false,
                enumerable: true,
                configurable: false
            });
        }
    });
    ig.Persistence.LocalStorage = ig.Class.extend({
        /**
         * Initialize Persistence as localStorage
         */
        init: function () {
            try {
                if (window.localStorage) {
                    ig.Persistence.instance = this;
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of local storage.");
            }
        },
        /**
         * Returns true if key is set, false otherwise
         */
        isSet: function (key) {
            return (this.get(key) !== 'undefined');
        },
        /**
         * Get a key's value
         */
        get: function (key, defaultValue) {
            var value = localStorage.getItem(key);
            if (value !== null) {
                if (value !== 'undefined') {
                    value = JSON.parse(value);
                    return value;
                } else {
                    throw new ig.PersistenceError("The value stored for " + "'" + key + "'" + " is undefined.");
                }
            } else if (typeof defaultValue !== 'undefined') {
                return defaultValue;
            } else {
                throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
            }
        },
        /**
         * Get a key's value as a Integer
         */
        getInt: function (key, defaultValue) {
            return parseInt(this.get(key, defaultValue), null);
        },
        /**
         * Get a key's value as a Float
         */
        getFloat: function (key, defaultValue) {
            return parseFloat(this.get(key, defaultValue));
        },
        /**
         * Get a key's value as a Boleean
         */
        getBool: function (key, defaultValue) {
            var value = this.get(key, defaultValue);
            switch (value.toLowerCase()) {
            case 'true':
                return true;
            case 'false':
                return false;
            default:
                throw new ig.PersistenceError("Value set for " + "'" + key + "'" + " is not boolean.");
            }
        },
        /**
         * Set a key's value, if it doesn't exist, it also creates the key
         */
        set: function (key, value) {
            try {
                window.localStorage.setItem(key, JSON.stringify(value));
            } catch (e) {
                throw new ig.PersistenceError("localStorage quota exceeded.");
            }
        },
        /**
         * Set a key's value if it's value is higher than the current persisted value
         */
        setHigher: function (key, value) {
            if (value > this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Set a key's value if it's value is lower than the current persisted value
         */
        setLower: function (key, value) {
            if (value < this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Remove a key and it's value from local storage
         */
        remove: function (key) {
            if (this.isSet(key)) {
                window.localStorage.removeItem(key);
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        },
        /**
         * Clears all keys and values on local storage
         */
        clear: function () {
            window.localStorage.clear();
        }
    });
    ig.Persistence.OtherFileSystem = ig.Class.extend({
        /**
         * Initialize Persistence as other file system
         */
        init: function () {
            console.log('we are using an alternative filesystem');
            ig.Persistence.instance = this;
        }
        /**
         * Continue implementation here
         */
    });
    return new ig.Persistence();
});

10 years ago by diligent

Thanks for sharing this!

10 years ago by FelipeBudinich

You're welcome diligent,

I'm wondering, is any feature am I missing that I should consider including? (or any pitfalls I'm not seeing?)

10 years ago by FelipeBudinich

Added a implementation using Node fs module, for use with node-webkit (do not use on server code, because it does synchronous calls)

/*global ig, process, require*/
ig.module(
    'plugin.persistence'
).requires(
    'impact.game'
).defines(function () {
    'use strict';
    ig.PersistenceError = function (message) {
        this.name = "PersistenceError";
        this.message = message;
    };
    ig.PersistenceError.prototype = Error.prototype;
    ig.Persistence = ig.Class.extend({
        currentSaveSlot: 0,
        /**
         * Create a static instance of this class
         */
        staticInstantiate: function (i) {
            this.alias('persistence');
            // for demostration purposes I'll create a ig.config object that contains the configuration we will be using
            ig.config = {};
            ig.config.persist = 'NodeWebkitFileSystem';
            switch (ig.config.persist) {
            case 'localStorage':
                ig.Persistence.inject(ig.Persistence.LocalStorage.prototype);
                break;
            case 'NodeWebkitFileSystem':
                ig.Persistence.inject(ig.Persistence.NodeWebkitFileSystem.prototype);
                break;
            default:
                throw new ig.PersistenceError("No persistence enviroment defined.");
            }
            return ig.Persistence.instance || null;
        },
        /**
         * Sets an alias that can be used to access this singleton
         */
        alias: function (name) {
            Object.defineProperty(ig, name, {
                value: this,
                writable: false,
                enumerable: true,
                configurable: false
            });
        },
        setSaveSlot: function (slot) {
            this.currentSaveSlot = slot;
        },
        getCurrentSaveSlot: function () {
            return this.currentSaveSlot;
        }
    });
    ig.Persistence.LocalStorage = ig.Class.extend({
        /**
         * Initialize Persistence as localStorage
         */
        init: function () {
            try {
                if (window.localStorage) {
                    ig.Persistence.instance = this;
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of localStorage.");
            }
        },
        /**
         * Returns true if key is set, false otherwise
         */
        isSet: function (key) {
            return (this.get(this.currentSaveSlot + key) !== 'undefined');
        },
        /**
         * Get a key's value
         */
        get: function (key, defaultValue) {
            var value = localStorage.getItem(this.currentSaveSlot + key);
            if (value !== null) {
                if (value !== 'undefined') {
                    value = JSON.parse(value);
                    return value;
                } else {
                    throw new ig.PersistenceError("The value stored for " + "'" + key + "'" + " is undefined.");
                }
            } else if (typeof defaultValue !== 'undefined') {
                return defaultValue;
            } else {
                throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
            }
        },
        /**
         * Get a key's value as a Integer
         */
        getInt: function (key, defaultValue) {
            return parseInt(this.get(key, defaultValue), null);
        },
        /**
         * Get a key's value as a Float
         */
        getFloat: function (key, defaultValue) {
            return parseFloat(this.get(key, defaultValue));
        },
        /**
         * Get a key's value as a Boleean
         */
        getBool: function (key, defaultValue) {
            var value = this.get(key, defaultValue);
            switch (value.toLowerCase()) {
            case 'true':
                return true;
            case 'false':
                return false;
            default:
                throw new ig.PersistenceError("Value set for " + "'" + key + "'" + " is not boolean.");
            }
        },
        /**
         * Set a key's value, if it doesn't exist, it also creates the key
         */
        set: function (key, value) {
            try {
                window.localStorage.setItem(this.currentSaveSlot + key, JSON.stringify(value));
            } catch (e) {
                throw new ig.PersistenceError("localStorage quota exceeded.");
            }
        },
        /**
         * Set a key's value if it's value is higher than the current persisted value
         */
        setHigher: function (key, value) {
            if (value > this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Set a key's value if it's value is lower than the current persisted value
         */
        setLower: function (key, value) {
            if (value < this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Remove a key and it's value from local storage
         */
        remove: function (key) {
            if (this.isSet(this.currentSaveSlot + key)) {
                window.localStorage.removeItem(this.currentSaveSlot + key);
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        }
    });
    ig.Persistence.NodeWebkitFileSystem = ig.Class.extend({
        /**
         * Initialize Persistence as other file system
         */
        init: function () {
            try {
                if (process.versions['node-webkit']) {
                    ig.Persistence.instance = this;
                    this.fs = require('fs');
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of accessing File System.");
            }
        },
        /**
         * Returns true if key is set, false otherwise
         */
        isSet: function (key) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                if (data.hasOwnProperty(key)) {
                    return true;
                } else {
                    return false;
                }
            } catch (e) {
                if (e.code === 'ENOENT') {
                    return false;
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Get a key's value
         */
        get: function (key, defaultValue) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                if (data.hasOwnProperty(key)) {
                    return data[key];
                } else if (typeof defaultValue !== 'undefined') {
                    return defaultValue;
                } else {
                    throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
                }
            } catch (e) {
                if (e.code === 'ENOENT') {
                    return defaultValue;
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Get a key's value as a Integer
         */
        getInt: function (key, defaultValue) {
            return parseInt(this.get(key, defaultValue), null);
        },
        /**
         * Get a key's value as a Float
         */
        getFloat: function (key, defaultValue) {
            return parseFloat(this.get(key, defaultValue));
        },
        /**
         * Get a key's value as a Boleean
         */
        getBool: function (key, defaultValue) {
            var value = this.get(key, defaultValue);
            if (value) {
                return true;
            } else if (!value) {
                return false;
            } else {
                throw new ig.PersistenceError("Value set for " + "'" + key + "'" + " is not boolean.");
            }
        },
        /**
         * Set a key's value, if it doesn't exist, it also creates the key
         */
        set: function (key, value) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                data[key] = value;
                data = JSON.stringify(data, null, 4);
                this.fs.writeFileSync(saveSlot, data);
            } catch (e) {
                if (e.code === 'ENOENT') {
                    data[key] = value;
                    data = JSON.stringify(data, null, 4);
                    this.fs.writeFileSync(saveSlot, data);
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Set a key's value if it's value is higher than the current persisted value
         */
        setHigher: function (key, value) {
            if (value > this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Set a key's value if it's value is lower than the current persisted value
         */
        setLower: function (key, value) {
            if (value < this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Remove a key and it's value
         */
        remove: function (key) {
            if (this.isSet(key)) {
                var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                    data = {};
                try {
                    data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                    delete data[key];
                    data = JSON.stringify(data, null, 4);
                    this.fs.writeFileSync(saveSlot, data);
                } catch (e) {
                    if (e.code === 'ENOENT') {
                        delete data[key];
                        data = JSON.stringify(data, null, 4);
                        this.fs.writeFileSync(saveSlot, data);
                    } else {
                        throw new ig.PersistenceError(e);
                    }
                }
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        }
    });
    return new ig.Persistence();
});

10 years ago by FelipeBudinich

Refactored some code:

/*global ig, process, require*/
ig.module(
    'plugins.persistence'
).requires(
    'impact.game'
).defines(function () {
    'use strict';
    ig.PersistenceError = function (message) {
        this.name = "PersistenceError";
        this.message = message;
    };
    ig.PersistenceError.prototype = Error.prototype;
    ig.Persistence = ig.Class.extend({
        currentSaveSlot: 0,
        /**
         * Create a static instance of this class
         */
        staticInstantiate: function (i) {
            this.alias('persistence');
            // for demostration purposes I'll create a ig.config object that contains the configuration we will be using
            ig.config = {};
            ig.config.persist = 'NodeWebkitFileSystem';
            switch (ig.config.persist) {
            case 'localStorage':
                ig.Persistence.inject(ig.Persistence.LocalStorage.prototype);
                break;
            case 'NodeWebkitFileSystem':
                ig.Persistence.inject(ig.Persistence.NodeWebkitFileSystem.prototype);
                break;
            default:
                throw new ig.PersistenceError("No persistence enviroment defined.");
            }
            return ig.Persistence.instance || null;
        },
        /**
         * Sets an alias that can be used to access this singleton
         */
        alias: function (name) {
            Object.defineProperty(ig, name, {
                value: this,
                writable: false,
                enumerable: true,
                configurable: false
            });
        },
        /**
         * Set current save slot
         */
        setSaveSlot: function (slot) {
            this.currentSaveSlot = slot;
        },
        /**
         * Get current save slot
         */
        getCurrentSaveSlot: function () {
            return this.currentSaveSlot;
        },
        /**
         * Get a key's value as a Integer
         */
        getInt: function (key, defaultValue) {
            return parseInt(this.get(key, defaultValue), null);
        },
        /**
         * Get a key's value as a Float
         */
        getFloat: function (key, defaultValue) {
            return parseFloat(this.get(key, defaultValue));
        },
        /**
         * Get a key's value as a Boleean
         */
        getBool: function (key, defaultValue) {
            var value = this.get(key, defaultValue);
            value = value.toString();
            switch (value) {
            case 'true':
                return true;
            case 'false':
                return false;
            default:
                throw new ig.PersistenceError("Value set for " + "'" + key + "'" + " is not boolean.");
            }
        },
        /**
         * Set a key's value if it's value is higher than the current persisted value
         */
        setHigher: function (key, value) {
            if (value > this.getFloat(key)) {
                this.set(key, value);
            }
        },
        /**
         * Set a key's value if it's value is lower than the current persisted value
         */
        setLower: function (key, value) {
            if (value < this.getFloat(key)) {
                this.set(key, value);
            }
        }
    });
    ig.Persistence.NodeWebkitFileSystem = ig.Class.extend({
        /**
         * Initialize Persistence as Node-Webkit file system
         */
        init: function () {
            try {
                if (process.versions['node-webkit']) {
                    ig.Persistence.instance = this;
                    this.fs = require('fs');
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of accessing File System.");
            }
        },
        /**
         * Returns true if key is set, false otherwise
         */
        isSet: function (key) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                if (data.hasOwnProperty(key)) {
                    return true;
                } else {
                    return false;
                }
            } catch (e) {
                if (e.code === 'ENOENT') {
                    return false;
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Get a key's value
         */
        get: function (key, defaultValue) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                if (data.hasOwnProperty(key)) {
                    return data[key];
                } else if (typeof defaultValue !== 'undefined') {
                    return defaultValue;
                } else {
                    throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
                }
            } catch (e) {
                if (e.code === 'ENOENT') {
                    return defaultValue;
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Set a key's value, if it doesn't exist, it also creates the key
         */
        set: function (key, value) {
            var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                data = {};
            try {
                data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                data[key] = value;
                data = JSON.stringify(data, null, 4);
                this.fs.writeFileSync(saveSlot, data);
            } catch (e) {
                if (e.code === 'ENOENT') {
                    data[key] = value;
                    data = JSON.stringify(data, null, 4);
                    this.fs.writeFileSync(saveSlot, data);
                } else {
                    throw new ig.PersistenceError(e);
                }
            }
        },
        /**
         * Remove a key and it's value
         */
        remove: function (key) {
            if (this.isSet(key)) {
                var saveSlot = 'saves/save_' + this.currentSaveSlot + '.json',
                    data = {};
                try {
                    data = JSON.parse(this.fs.readFileSync(saveSlot, 'utf8'));
                    delete data[key];
                    data = JSON.stringify(data, null, 4);
                    this.fs.writeFileSync(saveSlot, data);
                } catch (e) {
                    if (e.code === 'ENOENT') {
                        delete data[key];
                        data = JSON.stringify(data, null, 4);
                        this.fs.writeFileSync(saveSlot, data);
                    } else {
                        throw new ig.PersistenceError(e);
                    }
                }
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        }
    });
    ig.Persistence.LocalStorage = ig.Class.extend({
        /**
         * Initialize Persistence as localStorage
         */
        init: function () {
            try {
                if (window.localStorage) {
                    ig.Persistence.instance = this;
                }
            } catch (e) {
                throw new ig.PersistenceError("Enviroment is not capable of localStorage.");
            }
        },
        /**
         * Returns true if key is set, false otherwise
         */
        isSet: function (key) {
            return (this.get(this.currentSaveSlot + key) !== 'undefined');
        },
        /**
         * Get a key's value
         */
        get: function (key, defaultValue) {
            var value = localStorage.getItem(this.currentSaveSlot + key);
            if (value !== null) {
                if (value !== 'undefined') {
                    value = JSON.parse(value);
                    return value;
                } else {
                    throw new ig.PersistenceError("The value stored for " + "'" + key + "'" + " is undefined.");
                }
            } else if (typeof defaultValue !== 'undefined') {
                return defaultValue;
            } else {
                throw new ig.PersistenceError("No value stored for " + "'" + key + "'" + ", nor default value provided.");
            }
        },
        /**
         * Set a key's value, if it doesn't exist, it also creates the key
         */
        set: function (key, value) {
            try {
                window.localStorage.setItem(this.currentSaveSlot + key, JSON.stringify(value));
            } catch (e) {
                throw new ig.PersistenceError("localStorage quota exceeded.");
            }
        },
        /**
         * Remove a key and it's value from local storage
         */
        remove: function (key) {
            if (this.isSet(this.currentSaveSlot + key)) {
                window.localStorage.removeItem(this.currentSaveSlot + key);
            } else {
                throw new ig.PersistenceError("'" + key + "'" + " is not stored as a key.");
            }
        }
    });
    return new ig.Persistence();
});

I noticed that for each platform I only needed to rewrite "set", "get" and "isSet", while all other methods can be on the base ig.Persistence object.

Now I need to solve "how to make each module a different file"

10 years ago by eLouai

I just was looking for how to use html5 web storage.
It was remarkably simple.

No additional modules required.
Assumes HTML5 storage support (available since 2010)

Getting hiscore when starting game (init function in main)

this.hiscore = localStorage.getItem('hiscore');
if (this.hiscore == null) this.hiscore = 0;

Setting hiscore in player or main update loop or respawn or death function

if (ig.game.score > ig.game.hiscore)
{
    ig.game.hiscore = ig.game.score;
    localStorage.setItem('hiscore', ig.game.score);
}

Hope this helps others looking for the syntax for html5 web storage api.
Its that simple.

10 years ago by Apiheld

Yup, I used it too in a project and was very happy with it.

10 years ago by stahlmanDesign

Does anyone know how to get local storage like an AJAX call so there can be a callback on success? Right now I use it but with a hackish setTimeout that assumes it will load in 1 second. This might not always be true, and in many cases it is much faster.

10 years ago by drhayes

Nope, no async interface to localStorage. Storage API.

Are you hitting a performance limit on localStorage? I think you might be stuck using a retry loop with setTimeout or setInterval.

10 years ago by alexandre

Interesting question. This article written back in 2012 was discussing the possibility of non-blocking localStorage ops at some point in the future.

9 years ago by FelipeBudinich

I solved the multiple reads slowdown storing arrays instead of simple key values. (So far, I've only had one use case where I actually needed the speed)

By the way, I've improved this module quite a bit since I originally posted it, I'm doing some polishing and I'll upload it to a public repo soon.
Page 1 of 1
« first « previous next › last »