Menu Close

IndexedDB Manipulation with Dexie — Exceptions and Collections

IndexedDB is a way to store data in the browser.

It lets us store larger amounts of data than local storage in an asynchronous way.

Dexie makes working with IndexedDB easier.

In this article, we’ll take a look at how to start working with IndexedDB with Dexie.

Exception Handling

Exceptions will be handled if they happen in transactions.

For example, we can write:

const db = new Dexie("friends");

db.version(1).stores({
  friends: "id, name, *tags"
});

db.transaction('rw', db.friends, () => {
  window.MissSpelledVar.NonExistingVar = 3;
}).catch((err) => {
  console.error(err);
})

We call catch to catch the error with trying to access a property of a non-existent property.

If we catch an error within an operation, then the transaction won’t be aborted.

This is because the error is considered to be handled already.

So if we have:

const db = new Dexie("friends");

db.version(1).stores({
  friends: "id, name, *tags"
});

db.transaction('rw', db.friends, () => {
  db.friends.add({
    id: 1,
    name: "Foo"
  }).catch((e) => {
    console.error("Failed to add friend");
  });
}).catch((err) => {
  console.error(err);
})

Then the inner catch method would handle any errors with the db.friends.add call.

If we want to abort the transaction when an error is thrown, we’ve to rethrow the exception.

To do this, we write:

const db = new Dexie("friends");

db.version(1).stores({
  friends: "id, name, *tags"
});

db.transaction('rw', db.friends, () => {
  db.friends.add({
    id: 1,
    name: "Foo"
  }).catch((e) => {
    console.error("Failed to add friend");
    throw e;
  });
}).catch((err) => {
  console.error(err);
})

Collection

Collections represent collections of database objects.

They don’t contain any objects by themselves.

Instead, it yields a preparation for how to run a database query.

Collections return a promise with the data.

Add Multiple Criteria

We can add multiple criteria for our collection with the and method.

For example, we can write:

const db = new Dexie("friends");

db.version(1).stores({
  friends: "id, name, age"
});

(async () => {
  await db.friends.put({
    id: 1,
    name: "jane",
    age: 78
  });
  await db.friends.put({
    id: 2,
    name: "mary",
    age: 76
  });

  const someFriends = await db.friends
    .where("name")
    .equalsIgnoreCase("jane")
    .and(friends => friends.age > 50)
    .toArray()
  console.log(someFriends)
})()

We call and with a callback that returns the condition that we’re looking for to make the query.

Cloning Collections

We can clone a collection with the clone method.

For example, we can write:

const db = new Dexie("friends");

db.version(1).stores({
  friends: "id, name, age"
});

(async () => {
  await db.friends.put({
    id: 1,
    name: "jane",
    age: 78
  });
  await db.friends.put({
    id: 2,
    name: "mary",
    age: 76
  });

  await db.transaction('r', db.friends, function*() {
    const collection = db.friends.where('age').above(75);
    const clone = collection.clone().reverse().limit(1);
    const allOldFriends = yield collection.toArray();
    const oldestFriend = yield clone.toArray();
    console.log(allOldFriends)
    console.log(oldestFriend)
  }).catch(e => {
    console.error(e.stack);
  });
})()

We added 2 entries to the friends table.

Then we get all the friends with age above 75 with:

const collection = db.friends.where('age').above(75);

Then we call clone to clone the collection with:

const clone = collection.clone().reverse().limit(1);

Then we call toArray on both to get the results as arrays.

Then we should get the entries from the queries in the console.log .

Conclusion

We can handle exceptions and do various things with collections with Dexie.

Posted in JavaScript APIs