Accessing localStorage from a webWorker
Can a WebWorker access the localStorage?
If not why not? Is it problematic from a security stand point?
Solution 1:
Web workers only have access to the following:
XMLHttpRequest
- Application Cache
- Create other web workers
-
navigator
object -
location
object -
setTimeout
method -
clearTimeout
method -
setInterval
method -
clearInterval
method -
Performance
object (mark
,measure
,now
methods:caniuse?
) -
IndexedDB
API (see:caniuse?
) -
importScripts
method JSON
Worker
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:
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:
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.
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:
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:
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.