Browser database IndexedDB introductory tutorial
I. 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 is 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 does 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 transactions, 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. There is no situation where only part of the data is rewritten.
(4) Same origin restriction IndexedDB is subject to homology restriction, 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).
2. 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 recording
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,
id
attributes can be used as primary keys.
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.
Providing transaction object
error
,
abort
and
complete
three events to monitor operating results.
Three, operation process
Various operations of the IndexedDB database are generally carried out in accordance with the following process. This section only gives simple code examples for quick start. For detailed APIs of each object, please see here .
3.1 Open the database
The first step in using IndexedDB is to open the database and how to use
indexedDB.open()
it.
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
.
indexedDB.open()
The method returns an IDBRequest object.
The objects three events
error
, ,
success
,
upgradeneeded
handle open operating results database.
(1) error event
error
The event indicates a failure to open the database.
request.onerror = function (event) { console.log('数据库打开报错'); };
(2) Success event
success
The event indicates that the database was successfully opened.
var db; request.onsuccess = function (event) { db = request.result; console.log('数据库打开成功'); };
At this time, the
database object is
obtained through
request
the
result
properties of the object.
(3) Upgradeneeded event
If the specified version number is greater than the actual version number of the database, a database upgrade event will occur
upgradeneeded
.
var db; request.onupgradeneeded = function (event) { db = event.target.result; }
At this time
target.result
, the database instance is
obtained through the
properties of the
event object
.
3.2 Create a 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
upgradeneeded
event’s monitoring function, 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 new table called
person
, the primary key is added
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 designated as an attribute of the next-level object, for example
{ foo: { bar: 'baz' } }
,
foo.bar
can also be designated 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,
IDBObject.createIndex()
the three parameters are the index name, the attribute where the index is located, and the configuration object (indicating whether the attribute contains duplicate values).
3.3 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('数据写入成功'); }; request.onerror = function (event) { console.log('数据写入失败'); } } 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
IDBTransaction.objectStore(name)
creating a
new transaction, use the
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
events and
error
events of the
connection object
, you can know whether the write is successful.
3.4 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('事务失败'); }; 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('未获得数据记录'); } }; } 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.
3.5 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('没有更多数据了!'); } }; } readAll();
In the above code, the
openCursor()
method of
creating a pointer object
is an asynchronous operation, so the
success
event
should be monitored
.
3.6 Update data
The
IDBObject.put()
method
to be used to update the data
.
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('数据更新成功'); }; request.onerror = function (event) { console.log('数据更新失败'); } } update();
In the above code, the
put()
method automatically updates the
1
record whose
primary key is
.
3.7 Delete data
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('数据删除成功'); }; } remove();
3.8 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).
Assume that when
name
creating a
new table,
an index is created
on the
field.
objectStore.createIndex('name', 'name', { unique: false });
Now, you can
name
find the corresponding data record.
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 { // ... } }
(over)