2
\$\begingroup\$

I am making a plugin for Firefox, this is (more or less) my first time working with JavaScript. Is this a reasonable design for working with both values and lists in a database?

function set(key, value) {
    // Sets a key-value pair in the browser's local storage
    browser.storage.local.set({ [key]: value });
}

function get(key) {
    // Gets the value of a key from the browser's local storage
    return browser.storage.local.get(key)
}

function remove(key) {
    // Removes a key-value pair from the browser's local storage
    browser.storage.local.remove(key)
}

function getList(key) {
    // Gets a list from the browser's local storage
    return get(key).then(result => {
        if (result[key] === undefined) {
            return [];
        }
        return result[key];
    });
}

function pushToList(key, value) {
    // Pushes a value to a list in the browser's local storage
    getList(key).then(list => {
        list.push(value);
        set(key, list);
    });
}

function removeFromList(key, value) {
    // Removes a value from a list in the browser's local storage
    getList(key).then(list => {
        let index = list.indexOf(value);
        if (index > -1) {
            list.splice(index, 1);
            set(key, list);
        }
    });
}

export { set, get, remove, getList, pushToList, removeFromList };

Edit:

My end goal is to store things like settings (key, value) and lists of tabs and similar info (key, [value, value, value]). The code below is a library of functions to be used by the rest of my code.

Actually I do plan to store more complex json data as well, specifically I will store and edit Tab objects if that makes a difference.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ it may/may not matter but what sort of data are you storing (what is example list you plan to store/modify)? \$\endgroup\$ Commented Jan 20, 2023 at 11:32
  • \$\begingroup\$ This appears to be a library of functions. Did you test any of them? How? \$\endgroup\$ Commented Jan 20, 2023 at 11:44
  • \$\begingroup\$ @depperm edited my post to answer your question. \$\endgroup\$ Commented Jan 20, 2023 at 12:22

1 Answer 1

2
\$\begingroup\$

K.I.S (keep it simple)

KIS is a super important concept to keep in mind when coding. Making code more complex than needed, often done in anticipation of probable needs, will make

  1. Development time longer
  2. Code harder to maintain, modify and test.
  3. Waste clients CPU cycles.

The localStorage API is standardized and has had full support on all major browser for years

There is no need to use promises or async code as dot notation access to key, value pairs via localStorage is very fast.

Your functions set get remove are not needed as they are simple one liners.

When practical (low memory use) keep objects in memory and only use storage when there are changes.

Example code

Example of local storage use that keeps a copy in RAM. It only loads from storage at first use, and saves on changes. Not that it can add/remove many items before saving to storage.

Note that get list returns a copy of the list. Making changes to that list will not be stored.

Also note that all code is blocking (no async)

const local = {};
function removeFromList(name, ...items) {
    local[name] = load(name).filter(item => !items.includes(item));
    save(name);
}
function pushToList(name, ...items) {
    load(name).push(...items);
    save(name);
}
function getList(name) {
    return [...load(name)];
}
function save(name) {
    localStorage[name] = JSON.stringify(local[name]);
}
function load(name) {
    return local[name] ? 
        (localStorage[name] && JSON.parse(localStorage[name])) ? 
        [];
}

export {getList, pushToList, removeFromList};

Untrustable and insecure

Any form of client storage can not be trusted. Clients are free to delete, and modify (tamper) storage. 3rd parties also have access if the client grants them access (often clients are unaware what they expose).

Never store sensitive client data in local storage.

From a developers angle the example code (given above) needs to be wrapped in a try catch.

Style points

  • Remove comments that state the obvious. Eg you comment // Gets the value of a key from the browser's local storage before the line return browser.storage.local.get(key).

    How does your comment improve the readability of your code?

  • Don't expose what is not needed. You export all functions, I am not sure if the low level helper functions (get, set, remove) are of any use.

  • Aysnc code can generate errors. You have no error handling code?

  • Async code is great for async data, but should be avoided whenever you can as it breaks the trust you get from JS execution blocking.

    You have aysnc code in normal functions handling the same data

    Example you if call pushToList("a", 1); removeFromList("a", 1); you can not know when and if the push has completed. The remove may not find "a" and the "a" can be inserted after remove has resolved

    If you are using async function and there is a data dependency between these functions, the function involved should be async functions as well.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the feedback. The get, set and remove functions are actually written for actual anticipated needs. I will likely develop a feature where the user can switch between local and sync storage. In the sync situation I actually need the data to be updated live so the users data is kept in sync over different computers. Since this feature is anticipated, would you still recommend to have a local copy of the data in memory or would you read and write directly to sync storage? \$\endgroup\$ Commented Jan 30, 2023 at 12:48
  • \$\begingroup\$ Also, I though async was used to kind of prevent the asynchronous behavior by allowing me to use await. But you are probably correct that I have issues with my synchronization by reading and writing data quickly, especially if I use sync storage instead? \$\endgroup\$ Commented Jan 30, 2023 at 12:52

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.