Use of IndexedDB

Hello, I make use of session storage and local storage in one of my side projects but never make use of indexedDB. I'm currently learning a bit about it and just wanted to know where, when and why indexedDB can be helpul over session storage and local storage. Basically, from what I can see, it's like a NoSQL (kind of like mongoDB, which stores object store) database but it's a web storage. If anyone can share any use case where IndexedDB is prefered, would really appreciate.
46 Replies
Jochem
Jochem2w ago
I've never used it, and from what I've heard, it's mostly just a pain to work with
Faker
FakerOP2w ago
ah ok will skip learning it then 😂
Jochem
Jochem2w ago
entirely reasonable 😄
Faker
FakerOP2w ago
can we store things in the cache without making use of indexedDB?
Jochem
Jochem2w ago
you can use localstorage
Faker
FakerOP2w ago
yeah you are right, for me session storage and local storage do 99% of things that we need to maybe the 1% things is the indexedDB 😂
Jochem
Jochem2w ago
likely, yeah I imagine maybe if you're manually caching a ton of data client side that needs to be queryable, but that's very niche basically indexedDB is "know it exists, worry about it when you need it" for me
Faker
FakerOP2w ago
yep noted, will do the same
ἔρως
ἔρως2w ago
oh, yeah, avoid it at all costs it's preferable to use sqlite3 on wasm and shoving the data into localstorage than to use indexeddb indexeddb puts the devil in callback hell it was created and implemented before promises, so, the whole thing feels like you are walking on a bed of nails, but the nails are screaming hot just so you know, localstorage lets you store 5mb of data, so, you dont have to worry about it
Faker
FakerOP2w ago
yup noted
ἔρως
ἔρως2w ago
🤣 now i scared you away from it but seriously, there are wrappers on top of it you can use them, and they allow you to use promises with indexeddb the downside is that you are kinda stuck to a single wrapper
Faker
FakerOP2w ago
yep, will keep that if I will ever need it 😂
ἔρως
ἔρως2w ago
you very likely wont need it but its good to know it exists
13eck
13eck2w ago
The short version: you use it when you have no other option.
ἔρως
ἔρως2w ago
and even then ... sending the data to the server to store it is a better option there is just 1 thing it is good for: offline storage of content you're editing on a cms and even then ....
13eck
13eck2w ago
Yeah, off-line storage. So like if you’re making a podcast app or video app you can’t store that shit in local storage :p
ἔρως
ἔρως2w ago
i was more thinking about an article or a document or a presentation stuff like that or the project for a video editor
Mia
Mia2w ago
You can use a small wrapper like this if you want promise based api https://www.npmjs.com/package/idb IndexedDB has some advantages over localStorage for CERTAIN use cases: 1. Available in workers, you can store it in shared worker for example to get cross tab / per tab data. 2. It is possible to store unstringifiable data, which also has benefits for performance. 3. Transactions are async, your main thread isn't blocked on reading / writing NOT SMALL amount of data. 4. Builtin support for schema versioning is pretty nice. 5. Obviously it allows to store insane amount of data in comparison. As cons API is more complicated and it would actually be slower for working with SMALL amount of data.
ἔρως
ἔρως2w ago
"more complicated" is the understatement of the millenium that api is diabolical
13eck
13eck2w ago
You’re diabolical. But you’re also right 😜
ἔρως
ἔρως2w ago
im also left and a whole lot in the middle
Mia
Mia2w ago
I find API pretty straightforward to be honest.
ἔρως
ἔρως2w ago
it's callback hell on callback hell
Mia
Mia2w ago
People worked with same "callback hell" in node and somehow lived with it for years. It is all the same thing in the end, you can wrap it in promises if you really want, honestly not a problem.
ἔρως
ἔρως2w ago
im not saying it is a problem im saying it's an horrible api
Mia
Mia2w ago
Reasonable gripe is that API is on the lower level side of things
ἔρως
ἔρως2w ago
the api is absolutely horrible
Mia
Mia2w ago
What I get is that you just don't like callbacks
ἔρως
ἔρως2w ago
i don't care about callbacks i just hate an horrible api built on top of callback hell gigantic difference i think callbacks can be actually nice in some situations but indexeddb took them to the extreme end
Mia
Mia2w ago
Like can you provide reasons why the API is "horrible"? It is all very mild level, if you have worked with similar api in literally any other language that doesn't have async syntax too. Pretty typical for a design. Sounds more of a familiarity problem or something.
ἔρως
ἔρως2w ago
first, you open a database, then you have to have an event listener for a success, where you then get the actual object to be used then in that callback, you need to check for the version, which is in another event, where you have to manually upgrade the database to match what you expects for the new version now, lets see how it gets data from the database that's the part im not too familiar with, because i quit at seeing IDBCursor if it has a cursor, it's dogwater, in my opinion oh god, you need to open an object store to the get a cursor to read records from it oh, at least it's transaction based, so, should be pretty solid i got tired of trying to decode the api and i just decided to use duck.ai ... (it's my 3-4th time using ai for anything) it got me this mess:
// Open (or create) the database
const request = indexedDB.open('myDatabase', 1);

request.onupgradeneeded = function(event) {
const db = event.target.result;
// Create an object store if it doesn't exist
if (!db.objectStoreNames.contains('users')) {
db.createObjectStore('users', { keyPath: 'id' });
}
};

request.onsuccess = function(event) {
const db = event.target.result;
getUserByIndex(db, 14); // Get the 14th user
};

request.onerror = function(event) {
console.error('Database error:', event.target.errorCode);
};

// Function to get the 14th user
function getUserByIndex(db, index) {
const transaction = db.transaction('users', 'readonly');
const objectStore = transaction.objectStore('users');
const users = [];
let count = 0;

const cursorRequest = objectStore.openCursor();

cursorRequest.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
// Increment the count for each user
if (count === index - 1) { // index is 0-based, so 14th user is at index 13
console.log('14th user:', cursor.value);
}
count++;
cursor.continue(); // Move to the next record
} else {
if (count < index) {
console.log('Less than 14 users found.');
}
}
};

cursorRequest.onerror = function(event) {
console.error('Error retrieving users:', event.target.errorCode);
};
}
// Open (or create) the database
const request = indexedDB.open('myDatabase', 1);

request.onupgradeneeded = function(event) {
const db = event.target.result;
// Create an object store if it doesn't exist
if (!db.objectStoreNames.contains('users')) {
db.createObjectStore('users', { keyPath: 'id' });
}
};

request.onsuccess = function(event) {
const db = event.target.result;
getUserByIndex(db, 14); // Get the 14th user
};

request.onerror = function(event) {
console.error('Database error:', event.target.errorCode);
};

// Function to get the 14th user
function getUserByIndex(db, index) {
const transaction = db.transaction('users', 'readonly');
const objectStore = transaction.objectStore('users');
const users = [];
let count = 0;

const cursorRequest = objectStore.openCursor();

cursorRequest.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
// Increment the count for each user
if (count === index - 1) { // index is 0-based, so 14th user is at index 13
console.log('14th user:', cursor.value);
}
count++;
cursor.continue(); // Move to the next record
} else {
if (count < index) {
console.log('Less than 14 users found.');
}
}
};

cursorRequest.onerror = function(event) {
console.error('Error retrieving users:', event.target.errorCode);
};
}
please, tell me how this isn't as bad as i make it seem like i just asked it to give me the 14th user in the indexeddb database
Mia
Mia2w ago
14th user doesn't make much sense in the context of a DB, it would be a random record...
ἔρως
ἔρως2w ago
yes, it would as the ai decided, it is the id, which is close enough
Mia
Mia2w ago
function getUserById(db, id) {
const transaction = db.transaction('users', 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.get(id);
request.onsuccess = (event) => {
const res = event.target.result;
if (res) {
console.log(res)
} else {
console.log('User not found.');
}
}
request.onerror = (event) => {
console.error('Error retrieving users:', event.target.errorCode);
};
}
function getUserById(db, id) {
const transaction = db.transaction('users', 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.get(id);
request.onsuccess = (event) => {
const res = event.target.result;
if (res) {
console.log(res)
} else {
console.log('User not found.');
}
}
request.onerror = (event) => {
console.error('Error retrieving users:', event.target.errorCode);
};
}
by id would look similar, like this cursor is for iterating over non primary values
ἔρως
ἔρως2w ago
in php, using pdo, all that would be a single line:
$db->query('SELECT * FROM `users` WHERE id = 14');
$db->query('SELECT * FROM `users` WHERE id = 14');
Mia
Mia2w ago
It doesn't provide high-lever apis over cursors, which is a fair point, using libraries for that would make sense.
ἔρως
ἔρως2w ago
you also have to have the same 2-3 lines when you try to do anything at all gotta have the transaction and then get the object store and then you operate in the object store it's daunting
Zach Jensz
Zach Jensz2w ago
indexdb is one of the most powerful web APIs
ἔρως
ἔρως2w ago
i don't disagree but with great power, comes great power bills pain
Zach Jensz
Zach Jensz2w ago
v3 will improve the syntax https://www.w3.org/TR/IndexedDB/ for now use wrappers
ἔρως
ἔρως2w ago
wrap your wrapper in a wrapper so you can wrap while you wrap
Zach Jensz
Zach Jensz2w ago
@ἔρως you can use indexdb or OPFS as a backend for WASM sqlite
ἔρως
ἔρως2w ago
and you can use localstorage for it as well you don't want, but you can
Mia
Mia2w ago
what did they change? There is now a single API that returns a promise there, very encouraging.
Zach Jensz
Zach Jensz2w ago
many things, syntax being one. Read it yourself mate backwards compatibility was a major blocker
Mia
Mia2w ago
I don't see any major changes there skimming through the document you have linked. But in the WPT linked in that document API is promise based from what it seems, nice. They probably haven't started working on that draft yet Oh it is just their own wrapper okay okay. Don't see how it changes anything then.

Did you find this page helpful?