Accessing localStorage from a webWorker

JavascriptHtmlLocal StorageWeb Worker

Javascript Problem Overview


Can a WebWorker access the localStorage?

If not why not? Is it problematic from a security stand point?

Javascript Solutions


Solution 1 - Javascript

Web workers only have access to the following:

The window or parent objects are not accessible from a Web worker therefore you can't access the localStorage.

To communicate between window and the workerglobalscope you may use postMessage() function and onmessage event.

Accessing the DOM and window would not be thread safe, since the child thread would have the same privileges as its parent.

Solution 2 - Javascript

No, localStorage and sessionStorage are both undefined in a webworker process.

You would have to call postMessage() back to the Worker's originating code, and have that code store the data in localStorage.

Interestingly, a webworker can use an AJAX call to send/retrieve info to/from a server, so that may open possibilities, depending on what you're trying to do.

Solution 3 - Javascript

You can use IndexedDB in WebWorkers which is a way to store things locally in a key value store. It is not the same as localStorage, but it has similar use cases and can hold quite a lot of data. We use IndexedDB in WebWorkers at my work.

April 9th, 2021 EDIT:

For a minimal library that using indexeddb mirrors the local storage api but uses async rather than sync apis you could use idb-keyval which is located here. When writing large amounts of data it's better to use an async api like the above in JS, because it allows you to not block the thread.

April 21, 2020 EDIT:

The below edit for August 2019 no longer applies, it included information on the KV storage api which was an API that mirrored the localStorage API that was async and meant to be built on top of the Indexeddb API, as pointed out by @hoogw the KV Storage API is not currently being worked on to quote the KV storage spec:

> Work on this [KV strorage] specification is currently suspended, as no browser teams (including the Chromium project, which originated the proposal) are currently indicating interest in implementing it.

August 2019 EDIT:

There is a proposed API that might be out sometime in the future (although it's currently available in Chrome Canary with the experimental web features flag turned on). It's called KV Storage (KV is short for Key Value). It has an almost identical interface to the localStorage API and will come in JavaScript modules. It is built off of the indexeddb API, but has a much simpler API. Looking at the Spec it appears this is going to work in WebWorkers as well. For examples how to use it see the github page of the spec. Here is one such example:

import storage, { StorageArea } from "std:kv-storage";
import {test, assert} from "./florence-test";

test("kv-storage test",async () => {
  await storage.clear()
  await storage.set("mycat", "Tom");
  assert(await storage.get("mycat") === "Tom", "storage: mycat is Tom");

  const otherStorage = new StorageArea("unique string");
  await otherStorage.clear()
  assert(await otherStorage.get("mycat") === undefined, "otherStorage: mycat is undefined");
  await otherStorage.set("mycat", "Jerry");
  assert(await otherStorage.get("mycat") === "Jerry", "otherStorage: mycat is Jerry");
});

Here's the tests passing in Chrome Canary:

enter image description here

Although not necessary to use the kv-storage api the below code is the testing framework used for the above code:

// ./florence-test.js

// Ryan Florence's Basic Testing Framework modified to support async functions
// https://twitter.com/ryanflorence/status/1162792430422200320
const lock = AsyncLock();

export async function test (name, fn) {
  // we have to lock, so that console.groups are grouped together when
  // async functions are used.
  for await (const _ of lock) {
    console.group(name);
    await fn();
    console.groupEnd(name);
  }
};

export function assert (cond, desc) {
  if (cond) {
    console.log("%c✔️", "font-size: 18px; color: green", desc);
  } else {
    console.assert(cond, desc);
  }
};

// https://codereview.stackexchange.com/questions/177935/asynclock-implementation-for-js
function AsyncLock() { 
  const p = () => new Promise(next => nextIter = next ); 
  var nextIter, next = p(); 
  const nextP = () => { const result = next; next = result.then(() => p() ); return result;} 
  nextIter(); 
  return Object.assign({}, { 
    async * [Symbol.asyncIterator] () {
      try { 
        yield nextP() 
      } finally {
      nextIter() 
      } 
    }
  });
} 

Solution 4 - Javascript

kvStorage is a good alternative, however,

Dec, 2019. kvStorage currently is NOT, and will NOT be supported in chrome in future as well.

Work on this specification is currently suspended, as no browser teams (including the Chromium project, which originated the proposal) are currently indicating interest in implementing it.

Solution 5 - Javascript

Partytown can help here - https://github.com/builderio/partytown

With it, you can read/write main thread data from the worker thread, without having to build a bunch of postMessage protocols back and forth

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionciochPepView Question on Stackoverflow
Solution 1 - JavascriptfilipeView Answer on Stackoverflow
Solution 2 - JavascriptSpeednetView Answer on Stackoverflow
Solution 3 - JavascriptJohnView Answer on Stackoverflow
Solution 4 - JavascripthoogwView Answer on Stackoverflow
Solution 5 - JavascriptSteve8708View Answer on Stackoverflow