IndexedDB is a way for you to persistently store data inside a user’s browser. Because it lets you create web applications with rich query abilities regardless of network availability, these applications can work both online and offline. IndexedDB is useful for applications that store a large amount of data (for example, a catalog of DVDs in a lending library) and applications that don’t need persistent internet connectivity to work (for example, mail clients, to-do lists, and notepads).
If you have assumptions from working with other types of databases, you might get thrown off when working with IndexedDB. So keep the following important concepts in mind:
- IndexedDB databases store key-value pairs. The values can be complex structured objects, and keys can be properties of those objects. You can create indexes that use any property of the objects for quick searching, as well as sorted enumeration. Keys can be binary objects.
- IndexedDB is built on a transactional database model. Everything you do in IndexedDB always happens in the context of a transaction. The IndexedDB API provides lots of objects that represent indexes, tables, cursors, and so on, but each of these is tied to a particular transaction. Thus, you cannot execute commands or open cursors outside of a transaction. Transactions have a well-defined lifetime, so attempting to use a transaction after it has completed throws exceptions. Also, transactions auto-commit and cannot be committed manually.This transaction model is really useful when you consider what might happen if a user opened two instances of your web app in two different tabs simultaneously. Without transactional operations, the two instances could interfere with each other’s modifications. If you are not familiar with transactions in a database, read the Wikipedia article on transactions. Also see transaction under the Definitions section.
- The IndexedDB API is mostly asynchronous. The API doesn’t give you data by returning values; instead, you have to pass a callback function. You don’t “store” a value into the database, or “retrieve” a value out of the database through synchronous means. Instead, you “request” that a database operation happens. You get notified by a DOM event when the operation finishes, and the type of event you get lets you know if the operation succeeded or failed. This sounds a little complicated at first, but there are sanity measures baked in. It’s not that different from the way that XMLHttpRequest works.
- IndexedDB uses a lot of requests. Requests are objects that receive the success or failure DOM events that were mentioned previously. They have
onerrorproperties, and you can call
removeEventListener()on them. They also have
errorCodeproperties that tell you the status of the request. The
resultproperty is particularly magical, as it can be many different things, depending on how the request was generated (for example, an
IDBCursorinstance, or the key for a value that you just inserted into the database).
- IndexedDB uses DOM events to notify you when results are available. DOM events always have a
typeproperty (in IndexedDB, it is most commonly set to
"error"). DOM events also have a
targetproperty that indicates where the event is headed. In most cases, the
targetof an event is the
IDBRequestobject that was generated as a result of doing some database operation. Success events don’t bubble up and they can’t be canceled. Error events, on the other hand, do bubble, and can be cancelled. This is quite important, as error events abort whatever transactions they’re running in, unless they are cancelled.
- IndexedDB does not use Structured Query Language (SQL). It uses queries on an index that produces a cursor, which you use to iterate across the result set. If you are not familiar with NoSQL systems, read the Wikipedia article on NoSQL.
- IndexedDB adheres to a same-origin policy. An origin is the domain, application layer protocol, and port of a URL of the document where the script is being executed. Each origin has its own associated set of databases. Every database has a name that identifies it within an origin.The security boundary imposed on IndexedDB prevents applications from accessing data with a different origin. For example, while an app or a page in http://www.example.com/app/ can retrieve data from http://www.example.com/dir/, because they have the same origin, it cannot retrieve data from http://www.example.com:8080/dir/ (different port) or https://www.example.com/dir/ (different protocol), because they have different origins.