IndexedDB API

Overview

With the continuous enhancement of browser functions, more and more websites have begun to consider storing large amounts of data on the client side, which can reduce the data obtained from the server and obtain data directly from the local.

Existing browser data storage solutions are not suitable for storing large amounts of data: the size of cookies does not exceed 4KB, and each request will be sent back to the server; LocalStorage is between 2.5MB and 10MB (different from browser), and it is not Provide search function, can not build custom index. Therefore, a new solution is needed, and this is the background of the birth of IndexedDB.

In layman's terms, IndexedDB is the local database provided by the browser, which can be created and manipulated by web scripts. IndexedDB allows to store large amounts of data, provides a search interface, and can also create indexes. These are not available in LocalStorage. As far as the database type is concerned, IndexedDB is not a relational database (SQL query statements are not supported), and is closer to a NoSQL database.

IndexedDB has the following characteristics.

**(1) Key-value pair storage. ** IndexedDB internally uses an object store to store data. All types of data can be stored directly, including JavaScript objects. In the object warehouse, data is stored in the form of "key-value pairs". Each data record has a corresponding primary key. The primary key is unique and cannot be repeated, otherwise an error will be thrown.

**(2) Asynchronous. ** IndexedDB will not lock the browser during operation, and users can still perform other operations. This is in contrast to LocalStorage, which operates synchronously. Asynchronous design is to prevent the read and write of large amounts of data and slow down the performance of web pages.

**(3) Support affairs. ** IndexedDB supports transaction (transaction), which means that in a series of operation steps, as long as one step fails, the entire transaction is canceled, and the database is rolled back to the state before the transaction occurred, and there is no situation where only part of the data is rewritten.

**(4) Homologous restriction. ** IndexedDB is restricted by the same origin, and each database corresponds to the domain name that created it. Web pages can only access databases under their own domain names, but cannot access cross-domain databases.

**(5) Large storage space. ** The storage space of IndexedDB is much larger than that of LocalStorage, generally not less than 250MB, and there is even no upper limit.

**(6) Support binary storage. ** IndexedDB can store not only strings, but also binary data (ArrayBuffer objects and Blob objects).

basic concepts

IndexedDB is a relatively complex API, involving many concepts. It abstracts different entities into object interfaces. To learn this API is to learn its various object interfaces.

-Database: IDBDatabase object -Object store: IDBObjectStore object -Index: IDBIndex object -Transaction: IDBTransaction object -Operation request: IDBRequest object -Pointer: IDBCursor object -Primary key collection: IDBKeyRange object

The following are some of the main concepts.

(1) Database

A database is a container for a series of related data. Each domain name (strictly speaking, protocol + domain name + port) can create any number of databases.

IndexedDB database has the concept of version. Only one version of the database can exist at the same time. If you want to modify the database structure (add or delete tables, indexes, or primary keys), you can only complete it by upgrading the database version.

(2) Object warehouse

Each database contains several object stores. It is similar to a relational database table.

(3) Data logging

The object warehouse holds data records. Each record is similar to a row in a relational database, but only has two parts: the primary key and the data body. The primary key is used to create the default index and must be different, otherwise an error will be reported. The primary key can be an attribute in the data record, or it can be specified as an increasing integer number.

{id: 1, text:'foo'}

In the above object, the id attribute can be used as the primary key.

The data body can be any data type, not limited to objects.

(4) Index

In order to speed up data retrieval, you can build indexes for different attributes in the object warehouse.

(5) Affairs

The reading, writing, and deletion of data records must be completed through transactions. The transaction object provides three events of error, abort and complete to monitor the operation result.

Operating procedures

Various operations of the IndexedDB database are generally carried out in accordance with the following process. This section only gives a simple code example for quick start. The detailed API of each object will be introduced later.

Open the database

The first step in using IndexedDB is to open the database, using the indexedDB.open() method.

var request = window.indexedDB.open(databaseName, version);

This method accepts two parameters, the first parameter is a string, which represents the name of the database. If the specified database does not exist, a new database will be created. The second parameter is an integer, which represents the version of the database. If omitted, when opening an existing database, the default is the current version; when creating a new database, the default is 1.

The indexedDB.open() method returns an IDBRequest object. This object handles the operation result of opening the database through three events error, success, and upgradeneeded.

(1) error event

The error event indicates a failure to open the database.

request.onerror = function (event) {
  console.log("Database open error report");
};

(2) Success event

The success event indicates that the database was successfully opened.

var db;

request.onsuccess = function (event) {
  db = request.result;
  console.log("Database opened successfully");
};

At this time, the database object is obtained through the result property of the request object.

(3) upgradeneeded event

If the specified version number is greater than the actual version number of the database, the database upgrade event upgradeneeded will occur.

var db;

request.onupgradeneeded = function (event) {
  db = event.target.result;
};

At this time, the database instance is obtained through the target.result property of the event object.

New database

Creating a new database is the same operation as opening a database. If the specified database does not exist, it will be created. The difference is that the subsequent operations are mainly done in the listener function of the upgradeneeded event, because the version is created from scratch at this time, so this event will be triggered.

Usually, after creating a new database, the first thing is to create a new object warehouse (that is, create a new table).

request.onupgradeneeded = function (event) {
  db = event.target.result;
  var objectStore = db.createObjectStore("person", { keyPath: "id" });
};

In the above code, after the database is successfully created, a table called person is added, and the primary key is id.

A better way to write it is to first judge whether this table exists, and then create a new one if it does not exist.

request.onupgradeneeded = function (event) {
  db = event.target.result;
  var objectStore;
  if (!db.objectStoreNames.contains("person")) {
    objectStore = db.createObjectStore("person", { keyPath: "id" });
  }
};

The primary key (key) is an attribute that is indexed by default. For example, if the data record is { id: 1, name:'张三' }, then the id attribute can be used as the primary key. The primary key can also be specified as an attribute of the next-level object. For example, foo.bar of { foo: {bar:'baz'} } can also be specified as the primary key.

If there is no attribute in the data record that is suitable as the primary key, you can let IndexedDB automatically generate the primary key.

var objectStore = db.createObjectStore("person", { autoIncrement: true });

In the above code, the designated primary key is an increasing integer.

After creating a new object warehouse, you can create an index in the next step.

request.onupgradeneeded = function (event) {
  db = event.target.result;
  var objectStore = db.createObjectStore("person", { keyPath: "id" });
  objectStore.createIndex("name", "name", { unique: false });
  objectStore.createIndex("email", "email", { unique: true });
};

In the above code, the three parameters of IDBObject.createIndex() are the index name, the attribute where the index is located, and the configuration object (indicating whether the attribute contains duplicate values).

New data

New data refers to writing data records to the object warehouse. This needs to be done through transactions.

function add() {
  var request = db
    .transaction(["person"], "readwrite")
    .objectStore("person")
    .add({ id: 1, name: "张三", age: 24, email: "zhangsan@example.com" });

  request.onsuccess = function (event) {
    console.log("Data written successfully");
  };

  request.onerror = function (event) {
    console.log("Failed to write data");
  };
}

add();

In the above code, writing data requires a new transaction. When creating a new table, you must specify the table name and operation mode ("read-only" or "read-write"). After creating a new transaction, use the IDBTransaction.objectStore(name) method to get the IDBObjectStore object, and then use the add() method of the table object to write a record to the table.

The write operation is an asynchronous operation. By monitoring the success event and error event of the connection object, you can know whether the write is successful.

Read data

Reading data is also done through transactions.

function read() {
  var transaction = db.transaction(["person"]);
  var objectStore = transaction.objectStore("person");
  var request = objectStore.get(1);

  request.onerror = function (event) {
    console.log("Transaction failed");
  };

  request.onsuccess = function (event) {
    if (request.result) {
      console.log("Name: " + request.result.name);
      console.log("Age: " + request.result.age);
      console.log("Email: " + request.result.email);
    } else {
      console.log("Data record not obtained");
    }
  };
}

read();

In the above code, the objectStore.get() method is used to read the data, and the parameter is the value of the primary key.

Traverse the data

To traverse all the records of the data table, use the pointer object IDBCursor.

function readAll() {
  var objectStore = db.transaction("person").objectStore("person");

  objectStore.openCursor().onsuccess = function (event) {
    var cursor = event.target.result;

    if (cursor) {
      console.log("Id: " + cursor.key);
      console.log("Name: " + cursor.value.name);
      console.log("Age: " + cursor.value.age);
      console.log("Email: " + cursor.value.email);
      cursor.continue();
    } else {
      console.log("No more data!");
    }
  };
}

readAll();

In the above code, the openCursor() method of the newly created pointer object is an asynchronous operation, so the success event should be monitored.

update data

To update data, use the IDBObject.put() method.

function update() {
  var request = db
    .transaction(["person"], "readwrite")
    .objectStore("person")
    .put({ id: 1, name: "李四", age: 35, email: "lisi@example.com" });

  request.onsuccess = function (event) {
    console.log("Data update successfully");
  };

  request.onerror = function (event) {
    console.log("Data update failed");
  };
}

update();

In the above code, the put() method automatically updates the record whose primary key is 1.

delete data

The IDBObjectStore.delete() method is used to delete records.

function remove() {
  var request = db
    .transaction(["person"], "readwrite")
    .objectStore("person")
    .delete(1);

  request.onsuccess = function (event) {
    console.log("Data deleted successfully");
  };
}

remove();

Use Index

The significance of the index is that it allows you to search for any field, that is, to get data records from any field. If you do not build an index, you can only search for the primary key by default (that is, get the value from the primary key).

Suppose that when creating a new table, an index was created on the name field.

objectStore.createIndex("name", "name", { unique: false });

Now, you can find the corresponding data record from name.

var transaction = db.transaction(["person"], "readonly");
var store = transaction.objectStore("person");
var index = store.index("name");
var request = index.get("李四");

request.onsuccess = function (e) {
  var result = e.target.result;
  if (result) {
    // ...
  } else {
    // ...
  }
};

indexedDB object

The browser natively provides the indexedDB object as the developer's operating interface.

indexedDB.open()

The indexedDB.open() method is used to open the database. This is an asynchronous operation, but an IDBOpenDBRequest object will be returned immediately.

var openRequest = window.indexedDB.open("test", 1);

The above code indicates that a database named test and version 1 is opened. If the database does not exist, it will be created.

The first parameter of the open() method is the database name, the format is a string, and cannot be omitted; the second parameter is the database version, which is a positive integer greater than 0 (0 will report an error), if this If the parameter is greater than the current version, the database upgrade will be triggered. The second parameter can be omitted. If the database already exists, the current version of the database will be opened; if the database does not exist, the version of the database will be created, and the default version is 1.

Opening the database is an asynchronous operation, and the client is notified through various events. The following are 4 types of events that may be triggered.

-success: Successfully opened. -error: failed to open. -upgradeneeded: The database is opened for the first time, or the database version has changed. -blocked: The last database connection has not been closed.

When opening the database for the first time, the upgradeneeded event will be triggered first, and then the success event will be triggered.

According to different needs, monitor the above 4 kinds of events.

var openRequest = indexedDB.open("test", 1);
var db;

openRequest.onupgradeneeded = function (e) {
  console.log("Upgrading...");
};

openRequest.onsuccess = function (e) {
  console.log("Success!");
  db = openRequest.result;
};

openRequest.onerror = function (e) {
  console.log("Error");
  console.log(e);
};

There are two places to pay attention to in the above code. First, the open() method returns an object (IDBOpenDBRequest), and the listener function is defined on this object. Secondly, after the success event occurs, the opened IndexedDB database object can be obtained from the openRequest.result property.

indexedDB.deleteDatabase()

The indexedDB.deleteDatabase() method is used to delete a database, and the parameter is the name of the database. It will immediately return an IDBOpenDBRequest object, and then perform an asynchronous delete on the database. The result of the delete operation will be notified through events, and the IDBOpenDBRequest object can listen to the following events.

-success: Deleted successfully -error: delete the error

var DBDeleteRequest = window.indexedDB.deleteDatabase("demo");

DBDeleteRequest.onerror = function (event) {
  console.log("Error");
};

DBDeleteRequest.onsuccess = function (event) {
  console.log("success");
};

After calling the deleteDatabase() method, all other open connections of the current database will receive the versionchange event.

Note that deleting a database that does not exist will not report an error.

indexedDB.cmp()

The indexedDB.cmp() method compares whether two values ​​are the same primary key of indexedDB. It returns an integer indicating the result of the comparison: 0 means the same, 1 means the first primary key is greater than the second primary key, and -1 means the first primary key is smaller than the second primary key.

window.indexedDB.cmp(1, 2); // -1

Note that this method cannot be used to compare arbitrary JavaScript values. If the parameter is a boolean or object, it will report an error.

window.indexedDB.cmp(1, true); // error
window.indexedDB.cmp({}, {}); // report an error

IDBRequest object

The IDBRequest object represents an open database connection, and the indexedDB.open() method and the indexedDB.deleteDatabase() method will return this object. The operation of the database is done through this object.

All operations of this object are asynchronous operations. It is necessary to determine whether it is completed through the readyState property. If it is pending, it means the operation is in progress, if it is done, it means the operation is complete, which may succeed or fail.

After the operation is completed, the success event or the error event is triggered. At this time, the result of the operation can be obtained through the result attribute and the error attribute. If you read these two properties in the pending stage, an error will be reported.

The IDBRequest object has the following properties.

-IDBRequest.readyState: equal to pending means the operation is in progress, equal to done means the operation is being completed. -IDBRequest.result: returns the result of the request. If the request fails and the result is not available, an error will be reported when reading this attribute. -IDBRequest.error: When the request fails, the error object is returned. -IDBRequest.source: Returns the source of the request (such as index object or ObjectStore). -IDBRequest.transaction: Returns the ongoing transaction of the current request, if no transaction is included, returns null. -IDBRequest.onsuccess: Specify the listener function for the success event. -IDBRequest.onerror: Specify the listener function for the error event.

The IDBOpenDBRequest object inherits the IDBRequest object and provides two additional event monitoring properties.

-IDBOpenDBRequest.onblocked: Specify the listener function for the blocked event (the database is still in use when the upgradeneeded event is triggered). -IDBOpenDBRequest.onupgradeneeded: listener function for upgradeneeded event.

IDBDatabase Object

After opening the data successfully, you can get an IDBDatabase object from the result property of the IDBOpenDBRequest object, which represents the connected database. All subsequent operations on the database are done through this object.

var db;
var DBOpenRequest = window.indexedDB.open("demo", 1);

DBOpenRequest.onerror = function (event) {
  console.log("Error");
};

DBOpenRequest.onsuccess = function (event) {
  db = DBOpenRequest.result;
  // ...
};

Attributes

The IDBDatabase object has the following properties.

-IDBDatabase.name: string, database name. -IDBDatabase.version: integer, database version. When the database is first created, this attribute is an empty string. -IDBDatabase.objectStoreNames: DOMStringList objects (a collection of strings), the names of all object stores containing the current data. -IDBDatabase.onabort: Specify the listener function for the abort event (transaction abort). -IDBDatabase.onclose: Specify the listener function for the close event (database unexpectedly closed). -IDBDatabase.onerror: Specify the listener function for the error event (failure to access the database). -IDBDatabase.onversionchange: Triggered when the database version changes (upgradeneeded event occurs, or indexedDB.deleteDatabase() is called).

The following is an example of the objectStoreNames property. This property returns a DOMStringList object, which contains the names of all object warehouses in the current database (ie table names). You can use the contains method of the DOMStringList object to check whether the database contains an object warehouse.

if (!db.objectStoreNames.contains("firstOS")) {
  db.createObjectStore("firstOS");
}

The above code first determines whether an object warehouse exists, and if it does not exist, it creates the object warehouse.

Method

The IDBDatabase object has the following methods.

-IDBDatabase.close(): Close the database connection, it will actually wait for all transactions to complete before closing. -IDBDatabase.createObjectStore(): Create an object store for storing data, similar to a table in a traditional relational database, and return an IDBObjectStore object. This method can only be called in the versionchange event listener function. -IDBDatabase.deleteObjectStore(): delete the specified object store. This method can only be called in the versionchange event listener function. -IDBDatabase.transaction(): returns an IDBTransaction transaction object.

The following is an example of the createObjectStore() method.

var request = window.indexedDB.open("demo", 2);

request.onupgradeneeded = function (event) {
  var db = event.target.result;

  db.onerror = function (event) {
    console.log("error");
  };

  var objectStore = db.createObjectStore("items");

  // ...
};

The above code creates an object store named items, and if the object store already exists, an error will be thrown. To avoid errors, you need to use the objectStoreNames property below to check which object stores already exist.

The createObjectStore() method can also accept a second object parameter, which is used to set the properties of the object store.

db.createObjectStore("test", { keyPath: "email" });
db.createObjectStore("test2", { autoIncrement: true });

In the above code, the keyPath attribute represents the primary key (because the value of the primary key cannot be repeated, you must ensure that the value of the email attribute of the data is different before saving in the above example), the default value is null; autoIncrement The property indicates whether to use an auto-incrementing integer as the primary key (the first data record is 1, the second data record is 2, and so on), the default is false. Generally speaking, it is enough to use one of the keyPath and autoIncrement attributes. If the two are used at the same time, it means that the primary key is an increasing integer, and the object must not lack the attributes specified by the keyPath.

The following is an example of the deleteObjectStore() method.

var dbName = "sampleDB";
var dbVersion = 2;
var request = indexedDB.open(dbName, dbVersion);

request.onupgradeneeded = function (e) {
  var db = request.result;
  if (e.oldVersion < 1) {
    db.createObjectStore("store1");
  }

  if (e.oldVersion < 2) {
    db.deleteObjectStore("store1");
    db.createObjectStore("store2");
  }

  // ...
};

The following is an example of the transaction() method, which is used to create a database transaction and return an IDBTransaction object. Before adding data to the database, you must first create a database transaction.

var t = db.transaction(["items"], "readwrite");

The transaction() method accepts two parameters: the first parameter is an array, which is the object store involved, usually only one; the second parameter is a string representing the type of operation. Currently, there are only two types of operations: readonly (read-only) and readwrite (read-write). Use readwrite to add data, and readonly to read data. The second parameter is optional. When omitted, it defaults to readonly mode.

IDBObjectStore Object

The IDBObjectStore object corresponds to an object store. The IDBDatabase.createObjectStore() method returns an IDBObjectStore object.

The transaction() of the IDBDatabase object returns a transaction object, and the objectStore() method of this object returns an IDBObjectStore object, so the following chaining method can be used.

db.transaction(["test"], "readonly").objectStore("test").get(X).onsuccess =
  function (e) {};

Attributes

The IDBObjectStore object has the following properties.

-IDBObjectStore.indexNames: returns an array-like object (DOMStringList), which contains all the indexes of the current object store. -IDBObjectStore.keyPath: Returns the primary key of the current object store. -IDBObjectStore.name: Returns the name of the current object store. -IDBObjectStore.transaction: Returns the transaction object to which the current object store belongs. -IDBObjectStore.autoIncrement: Boolean value, indicating whether the primary key will be automatically incremented.

Method

The IDBObjectStore object has the following methods.

(1) IDBObjectStore.add()

IDBObjectStore.add() is used to add data to the object store and returns an IDBRequest object. This method is only used to add data. If the primary key is the same, an error will be reported, so the put() method must be used to update the data.

objectStore.add(value, key);

This method accepts two parameters. The first parameter is the key value, and the second parameter is the primary key. This parameter is optional. If omitted, the default is null.

After creating the transaction, you can get the object warehouse, and then use the add() method to add data to it.

var db;
var DBOpenRequest = window.indexedDB.open("demo", 1);

DBOpenRequest.onsuccess = function (event) {
  db = DBOpenRequest.result;
  var transaction = db.transaction(["items"], "readwrite");

  transaction.oncomplete = function (event) {
    console.log("transaction success");
  };

  transaction.onerror = function (event) {
    console.log("transaction error: " + transaction.error);
  };

  var objectStore = transaction.objectStore("items");
  var objectStoreRequest = objectStore.add({ foo: 1 });

  objectStoreRequest.onsuccess = function (event) {
    console.log("add data success");
  };
};

(2) IDBObjectStore.put()

The IDBObjectStore.put() method is used to update the data record corresponding to a primary key. If the corresponding key value does not exist, a new record is inserted. This method returns an IDBRequest object.

objectStore.put(item, key);

This method accepts two parameters, the first parameter is the new data, and the second parameter is the primary key. This parameter is optional and only necessary for auto-increment, because the primary key is not included in the data value at that time.

(3) IDBObjectStore.clear()

IDBObjectStore.clear() deletes all records in the current object store. This method returns an IDBRequest object.

objectStore.clear();

This method does not require parameters.

(4) IDBObjectStore.delete()

The IDBObjectStore.delete() method is used to delete the record of the specified primary key. This method returns an IDBRequest object.

objectStore.delete(Key);

The parameter of this method is the value of the primary key.

(5) IDBObjectStore.count()

The IDBObjectStore.count() method is used to count the number of records. This method returns an IDBRequest object.

IDBObjectStore.count(key);

Without parameters, this method returns the number of all records in the current object warehouse. If the primary key or IDBKeyRange object is used as a parameter, the corresponding number of records is returned.

(6) IDBObjectStore.getKey()

IDBObjectStore.getKey() is used to get the primary key. This method returns an IDBRequest object.

objectStore.getKey(key);

The parameter of this method can be a primary key value or an IDBKeyRange object.

(7) IDBObjectStore.get()

IDBObjectStore.get() is used to get the data record corresponding to the primary key. This method returns an IDBRequest object.

objectStore.get(key);

(8) IDBObjectStore.getAll()

DBObjectStore.getAll() is used to get the records of the object store. This method returns an IDBRequest object.

// Get all records
objectStore.getAll();

// Get all records that match the specified primary key or IDBKeyRange
objectStore.getAll(query);

// Specify the number of records to get
objectStore.getAll(query, count);

(9) IDBObjectStore.getAllKeys()

IDBObjectStore.getAllKeys() is used to get all eligible primary keys. This method returns an IDBRequest object.

// Get the primary key of all records
objectStore.getAllKeys();

// Get all eligible primary keys
objectStore.getAllKeys(query);

// Specify the number of primary keys
objectStore.getAllKeys(query, count);

(10) IDBObjectStore.index()

The IDBObjectStore.index() method returns the index object IDBIndex with the specified name.

objectStore.index(name);

With the index, you can read data for the attribute where the index is located.

var t = db.transaction(["people"], "readonly");
var store = t.objectStore("people");
var index = store.index("name");

var request = index.get("foo");

After the above code opens the object warehouse, first use the index() method to specify the index to get the name attribute, and then use the get() method to read the data corresponding to a certain name attribute (foo). If the name attribute does not correspond to a unique value, then the get() method may retrieve multiple data objects. In addition, get() is an asynchronous method. After the reading is successful, the data can only be processed in the listener function of the success event.

(11) IDBObjectStore.createIndex()

The IDBObjectStore.createIndex() method is used to create an index in the current database. This method can only be called in the VersionChange listener function.

objectStore.createIndex(indexName, keyPath, objectParameters);

The method can accept three parameters.

-indexName: index name -keyPath: Primary key -objectParameters: configuration object (optional)

The third parameter can configure the following properties.

-unique: If set to true, duplicate values ​​will not be allowed -multiEntry: If set to true, for a primary key array with multiple values, each value will create an entry in the index, otherwise the primary key array corresponds to an entry.

Assume that the data records in the object warehouse are all of the following person type.

var person = {
  name: name,
  email: email,
  created: new Date(),
};

You can specify an attribute of this object to create an index.

var store = db.createObjectStore("people", { autoIncrement: true });

store.createIndex("name", "name", { unique: false });
store.createIndex("email", "email", { unique: true });

The above code tells the index object that the name attribute is not a unique value, and the email attribute is a unique value.

(12) IDBObjectStore.deleteIndex()

The IDBObjectStore.deleteIndex() method is used to delete the specified index. This method can only be called in the VersionChange listener function.

objectStore.deleteIndex(indexName);

(13) IDBObjectStore.openCursor()

IDBObjectStore.openCursor() is used to obtain a pointer object.

IDBObjectStore.openCursor();

Pointer objects can be used to traverse data. This object is also asynchronous and has its own success and error events, and you can specify listening functions for them.

var t = db.transaction(["test"], "readonly");
var store = t.objectStore("test");

var cursor = store.openCursor();

cursor.onsuccess = function (event) {
  var res = event.target.result;
  if (res) {
    console.log("Key", res.key);
    console.dir("Data", res.value);
    res.continue();
  }
};

The listener function accepts an event object as a parameter, and the target.result property of this object points to the current data record. The key and value of this record respectively return the primary key and key value (that is, the actual stored data). The continue() method moves the cursor to the next data object. If the current data object is the last data object, the cursor points to null.

The first parameter of the openCursor() method is the primary key value, or an IDBKeyRange object. If this parameter is specified, only the records containing the specified primary key will be processed; if omitted, all records will be processed. This method can also accept a second parameter, which represents the traversal direction. The default value is next, and other possible values ​​are prev, nextunique and prevunique. The last two values ​​indicate that if duplicate values ​​are encountered, they will be skipped automatically.

(14) IDBObjectStore.openKeyCursor()

IDBObjectStore.openKeyCursor() is used to obtain a primary key pointer object.

IDBObjectStore.openKeyCursor();

IDBTransaction object

The IDBTransaction object is used to asynchronously operate database transactions, and all read and write operations must be performed through this object.

The IDBDatabase.transaction() method returns an IDBTransaction object.

var db;
var DBOpenRequest = window.indexedDB.open("demo", 1);

DBOpenRequest.onsuccess = function (event) {
  db = DBOpenRequest.result;
  var transaction = db.transaction(["demo"], "readwrite");

  transaction.oncomplete = function (event) {
    console.log("transaction success");
  };

  transaction.onerror = function (event) {
    console.log("transaction error: " + transaction.error);
  };

  var objectStore = transaction.objectStore("demo");
  var objectStoreRequest = objectStore.add({ foo: 1 });

  objectStoreRequest.onsuccess = function (event) {
    console.log("add data success");
  };
};

The order of execution of transactions is in the order in which they are created, not in the order in which the requests are issued.

var trans1 = db.transaction("foo", "readwrite");
var trans2 = db.transaction("foo", "readwrite");
var objectStore2 = trans2.objectStore("foo");
var objectStore1 = trans1.objectStore("foo");
objectStore2.put("2", "key");
objectStore1.put("1", "key");

In the above code, the key value corresponding to key is ultimately 2 instead of 1. Because the transaction trans1 was created before trans2, it is executed first.

Note that the transaction may fail. Only by monitoring the complete event of the transaction can the successful operation of the transaction be guaranteed.

The IDBTransaction object has the following properties.

-IDBTransaction.db: Returns the database object IDBDatabase where the current transaction is located. -IDBTransaction.error: Returns the error of the current transaction. If the transaction does not end, or the transaction ends successfully, or is manually terminated, the method returns null. -IDBTransaction.mode: Returns the mode of the current transaction, the default is readonly (read-only), and the other value is readwrite. -IDBTransaction.objectStoreNames: returns an array-like object DOMStringList, the member is the name of the object store involved in the current transaction. -IDBTransaction.onabort: Specify the listener function for the abort event (transaction interruption). -IDBTransaction.oncomplete: Specify the listener function for the complete event (transaction success). -IDBTransaction.onerror: Specify the listener function for the error event (transaction failure).

The IDBTransaction object has the following methods.

-IDBTransaction.abort(): Terminate the current transaction and roll back all changes that have been made. -IDBTransaction.objectStore(name): Returns the object store IDBObjectStore with the specified name.

IDBIndex Object

The IDBIndex object represents the index of the database, through which the records in the database can be obtained. The primary key of the data record is indexed by default, and the IDBIndex object is mainly used to obtain objects through indexes other than the primary key.

IDBIndex is a persistent storage of key-value pairs. As long as data records are inserted, updated or deleted, the records in the referenced object library will be automatically updated.

The IDBObjectStore.index() method can obtain IDBIndex objects.

var transaction = db.transaction(["contactsList"], "readonly");
var objectStore = transaction.objectStore("contactsList");
var myIndex = objectStore.index("lName");

myIndex.openCursor().onsuccess = function (event) {
  var cursor = event.target.result;
  if (cursor) {
    var tableRow = document.createElement("tr");
    tableRow.innerHTML =
      "<td>" +
      cursor.value.id +
      "</td>" +
      "<td>" +
      cursor.value.lName +
      "</td>" +
      "<td>" +
      cursor.value.fName +
      "</td>" +
      "<td>" +
      cursor.value.jTitle +
      "</td>" +
      "<td>" +
      cursor.value.company +
      "</td>" +
      "<td>" +
      cursor.value.eMail +
      "</td>" +
      "<td>" +
      cursor.value.phone +
      "</td>" +
      "<td>" +
      cursor.value.age +
      "</td>";
    tableEntry.appendChild(tableRow);

    cursor.continue();
  } else {
    console.log("Entries all displayed.");
  }
};

The IDBIndex object has the following properties.

-IDBIndex.name: string, the name of the index. -IDBIndex.objectStore: The object store where the index is located. -IDBIndex.keyPath: the primary key of the index. -IDBIndex.multiEntry: Boolean value, for the case that keyPath is an array, if it is set to true, each array member will have one entry when creating the array, otherwise each array has only one entry. -IDBIndex.unique: Boolean value, indicating whether the same primary key is allowed when creating an index.

The IDBIndex object has the following methods, all of which are asynchronous, and an IDBRequest object is returned immediately.

-IDBIndex.count(): used to get the number of records. It can accept a primary key or an IDBKeyRange object as a parameter, then only the number of records matching the primary key is returned, otherwise the number of all records is returned. -IDBIndex.get(key): used to get data records that match the specified primary key. -IDBIndex.getKey(key): used to get the specified primary key. -IDBIndex.getAll(): used to get all data records. It can accept two parameters, both of which are optional. The first parameter is used to specify the primary key, and the second parameter is used to specify the number of returned records. If these two parameters are omitted, all records are returned. Since the browser must generate all objects when the acquisition is successful, it has an impact on performance. If the data set is relatively large, it is recommended to use the IDBCursor object. -IDBIndex.getAllKeys(): This method is similar to the IDBIndex.getAll() method, the difference is to get all the primary keys. -IDBIndex.openCursor(): used to get an IDBCursor object, used to traverse all items in the index. -IDBIndex.openKeyCursor(): This method is similar to the IDBIndex.openCursor() method, the difference is to traverse the primary key of all entries.

IDBCursor Object

The IDBCursor object represents a pointer object, which is used to traverse the records of the data warehouse (IDBObjectStore) or index (IDBIndex).

IDBCursor objects are generally obtained through the IDBObjectStore.openCursor() method.

var transaction = db.transaction(['rushAlbumList'],'readonly');
var objectStore = transaction.objectStore('rushAlbumList');

objectStore.openCursor(null,'next').onsuccess = function(event) {
  var cursor = event.target.result;
  if (cursor) {
    var listItem = document.createElement('li');
      listItem.innerHTML = cursor.value.albumTitle +', '+ cursor.value.year;
      list.appendChild(listItem);

      console.log(cursor.source);
      cursor.continue();
    } else {
      console.log('Entries all displayed.');
    }
  };
};

The properties of the IDBCursor object.

-IDBCursor.source: Returns the object warehouse or index being traversed. -IDBCursor.direction: a string indicating the direction of the pointer traversal. There are four possible values: next (traverse backward from the beginning), nextunique (traverse backward from the beginning, repeated values ​​are traversed only once), prev (traverse forward from the tail), prevunique (traverse forward from the tail) , Repeated values ​​are only traversed once). This attribute is specified by the second parameter of the IDBObjectStore.openCursor() method. Once specified, it cannot be changed. -IDBCursor.key: Returns the primary key of the current record. -IDBCursor.value: Returns the data value of the current record. -IDBCursor.primaryKey: Returns the primary key of the current record. For the data warehouse (objectStore), this attribute is equivalent to IDBCursor.key; for the index, IDBCursor.key returns the position value of the index, and this attribute returns the primary key of the data record.

The IDBCursor object has the following methods.

-IDBCursor.advance(n): The pointer moves forward n positions. -IDBCursor.continue(): The pointer moves forward one position. It can accept a primary key as a parameter, then it will jump to this primary key. -IDBCursor.continuePrimaryKey(): This method requires two parameters, the first is key, the second is primaryKey, move the pointer to the position that meets these two parameters. -IDBCursor.delete(): Used to delete the record at the current position and return an IDBRequest object. This method does not change the position of the pointer. -IDBCursor.update(): used to update the record of the current position and return an IDBRequest object. Its parameter is the new value to be written to the database.

IDBKeyRange object

The IDBKeyRange object represents a set of primary keys in the object store. According to this set of primary keys, a set of records in the data warehouse or index can be obtained.

IDBKeyRange can contain only one value, or you can specify upper and lower limits. It has four static methods to specify the range of the primary key.

-IDBKeyRange.lowerBound(): Specify the lower limit. -IDBKeyRange.upperBound(): Specify the upper limit. -IDBKeyRange.bound(): Specify the upper and lower limits at the same time. -IDBKeyRange.only(): Specify that only one value is included.

Below are some code examples.

// All keys ≤ x
var r1 = IDBKeyRange.upperBound(x);

// All keys <x
var r2 = IDBKeyRange.upperBound(x, true);

// All keys ≥ y
var r3 = IDBKeyRange.lowerBound(y);

// All keys> y
var r4 = IDBKeyRange.lowerBound(y, true);

// All keys ≥ x && ≤ y
var r5 = IDBKeyRange.bound(x, y);

// All keys> x &&< y
var r6 = IDBKeyRange.bound(x, y, true, true);

// All keys> x && ≤ y
var r7 = IDBKeyRange.bound(x, y, true, false);

// All keys ≥ x &&< y
var r8 = IDBKeyRange.bound(x, y, false, true);

// The key = z
var r9 = IDBKeyRange.only(z);

The three methods IDBKeyRange.lowerBound(), IDBKeyRange.upperBound(), and IDBKeyRange.bound() include endpoint values ​​by default. You can pass in a boolean value to modify this property.

Correspondingly, the IDBKeyRange object has four read-only properties.

-IDBKeyRange.lower: return to the lower limit -IDBKeyRange.lowerOpen: Boolean value, indicating whether the lower limit is an open range (that is, whether the lower limit is excluded from the range) -IDBKeyRange.upper: return the upper limit -IDBKeyRange.upperOpen: Boolean value, indicating whether the upper limit is an open range (that is, whether the upper limit is excluded from the range)

After the IDBKeyRange instance object is generated, input it as a parameter to the openCursor() method of IDBObjectStore or IDBIndex object, and the data can be read within the set range.

var t = db.transaction(["people"], "readonly");
var store = t.objectStore("people");
var index = store.index("name");

var range = IDBKeyRange.bound("B", "D");

index.openCursor(range).onsuccess = function (e) {
  var cursor = e.target.result;
  if (cursor) {
    console.log(cursor.key + ":");

    for (var field in cursor.value) {
      console.log(cursor.value[field]);
    }
    cursor.continue();
  }
};

IDBKeyRange has an instance method includes(key), which returns a boolean value indicating whether a certain primary key is included in the current primary key group.

var keyRangeValue = IDBKeyRange.bound("A", "K", false, false);

keyRangeValue.includes("F"); // true
keyRangeValue.includes("W"); // false