Read the text and write down relevant points.

You will need to have knowledge of Service Workers concepts and the implementation of IndexedDB in Service Workers.

start

Single-page applications basically require Web services to install data. Data is injected into the DOM through the controller. Most front-end frameworks do this.

You can cache static web pages and resource files, especially browsing data, but when there is no network, users can read from the local database cache.

IndexedDB is a replacement for the deprecated Web SQL database. A NoSQL key-value pair database that supports very large storage (up 20-50% of hard disk space). Supports data types number, string, JSON, BLOb, and more.

IndexedDB complies with the same origin policy. This means that different applications cannot access each other’s databases. This is an event-driven, transactional, atomic, API asynchronous database. It is supported by all major browsers and will be supported if it is not. Great for storing offline data.

IndexedDB 2.0 is a worthwhile look. Although all browsers do not support it.

Let me just use a couple of little apis. I have the documentation here.

introduce

The IndexedDB consists of multiple Object Stores. Like MySQL tables, MongoDB collections. Each store has multiple objects. It’s like a row in a MySQL table.

Object Stores can record multiple rows and are key-value pairs. Each row is sorted by key ascending. There can be only one unique Object Store name in the database. A database is created at version 1. The database cannot have multiple versions.

Can be connected by multiple clients, read and write operations are transactional,

Key types: string, date, float, a binary blob, or an array.

Value: Boolean, number, string, date, object, array, regEXP, undefined and null.

Basic operations with IndexedDB:

  • Open the database.
  • Create an Object Store.
  • Transactionally perform database operations, such as adding or retrieving data.
  • Wait for the operation to complete by listening for events.
  • Sit on something with the readout.

It is available in the global scope of both Windows and service workers. Check whether window.indexeddb or self.indexeddb is supported.

if(self.IndexedDB){
    console.log('IndexedDB is supported');
}
Copy the code

.open(dbName, versionInt) Opens the database. Pass in the name and version number.

If the database does not exist, create one. If the version number is high, the database uses the new version instead of the old data. Event-driven, you know. The open method triggers Success, Error, and upgradenneeded. Like me:

var request = self.IndexedDB.open('EXAMPLE_DB', 1);
var db;
request.onsuccess = function(event) {
    console.log('[onsuccess]', request.result);
    db = event.target.result; // === request.result
};
request.onerror = function(event) {
    console.log('[onerror]', request.error);
};
Copy the code

In the callback, event.target === request. Request. Result is the result.

Remember to handle errors in onError.

In the developer tools, Application > IndexedDB is available.

Onupgradenneeded is triggered when a new database or version is opened.

request.onupgradeneeded = function(event) {
    // create object store from db or event.target.result
};
Copy the code

CreateObjectStore () Creates an ObjectStore.

db.createObjectStore(storeName, options);
Copy the code

StoreName is also unique. Options has two properties. Options. keyPath is the field name. (similar to the Key

request.onupgradeneeded = function(event) {
    var db = event.target.result;
    var store = db.createObjectStore('products', {keyPath: 'id'});
};
Copy the code

Function as shown in figure:

To increment the Key, use options.autoIncrement = true

The combination effect of each option is as follows:

IndexedDB has indexes. Indexes and can have unique constraints.

store.createIndex(indexName, keyPath, options);
Copy the code

IndexName indexName. KeyPath Key on which the index is established. The options are optional. {unique: true} If the above configuration is used, duplicate Key values cannot be added.

request.onupgradeneeded = function(event) {
    var db = event.target.result;
    var store = db.createObjectStore('products', {keyPath: 'id'});
// create unique index on keyPath === 'id'
    store.createIndex('products_id_unqiue, 'id', {unique: true});
};
Copy the code

Once the onupgradenrequired event is complete, the SUCCESS event is triggered.

var transaction = db.transaction(storeName, mode);
var transaction = db.transaction(storeNamesArray, mode);
Copy the code

Returns the number of operation permissions based on store.

Mode The optional parameter is readonly readwrite versionchange.

var objectStore = transaction.objectStore(storeName);
Copy the code

When the operation succeeds, the complete event is raised. Abort () can roll back a transaction.

About the transaction

ObjectStore is an instance of the IDBObjectStore interface that provides operations such as GET, Add, clear, count, PUT, and delete.

var request = self.IndexedDB.open('EXAMPLE_DB', 1); request.onsuccess = function(event) { // some sample products data var products = [ {id: 1, name: 'Red Men T-shirt ', price: '$3.99'}, {id: 2, name: 'Pink Women Shorts', price: '$5.99'}, {id: 3, name: 'Pink Women Shorts', price: '$5.99'}, {id: 3, name: 'Nike white Shoes', price: '$300'} ]; // get database from event var db = event.target.result; // create transaction from database var transaction = db.transaction('products', 'readwrite'); // add success event handleer for transaction // you should also add onerror, onabort event handlers transaction.onsuccess = function(event) { console.log('[Transaction] ALL DONE! '); }; // get store from transaction // returns IDBObjectStore instance var productsStore = transaction.objectStore('products'); // put products data in productsStore products.forEach(function(product){ var db_op_req = productsStore.add(product); // IDBRequest }); };Copy the code

= for the sake of simplicity

var db_op_req = productsStore.add(product);
db_op_req.onsuccess = function(event) {
    console.log(event.target.result == product.id); // true
};
db_op_req.onerror = function(event) {
    // handle error
};
Copy the code

CRUD:

  • objectStore.add(data)
  • objectStore.get(key)
  • objectStore.getAll()
  • objectStore.count(key?)
  • objectStore.getAllKeys()
  • objectStore.put(data, key?)
  • objectStore.delete(key)
  • objectStore.clear()

See IDBObjectStore

Close Closes the database connection. The database is not shut down until all transactions have completed. But if you close early, no new transactions will be created.

var request = self.indexedDB.open('EXAMPLE_DB', 1); request.onsuccess = function(event) { // some sample products data var products = [ {id: 1, name: 'Red Men T-shirt ', price: '$3.99'}, {id: 2, name: 'Pink Women Shorts', price: '$5.99'}, {id: 3, name: 'Pink Women Shorts', price: '$5.99'}, {id: 3, name: 'Nike white Shoes', price: '$300'} ]; // get database from event var db = event.target.result; // create transaction from database var transaction = db.transaction('products', 'readwrite'); // add success event handleer for transaction // you should also add onerror, onabort event handlers transaction.onsuccess = function(event) { console.log('[Transaction] ALL DONE! '); }; // get store from transaction var productsStore = transaction.objectStore('products'); /*************************************/ // put products data in productsStore products.forEach(function(product){ var db_op_req = productsStore.add(product); db_op_req.onsuccess = function(event) { console.log(event.target.result == product.id); // true } }); // count number of objects in store productsStore.count().onsuccess = function(event) { console.log('[Transaction - COUNT] number of products in store', event.target.result); }; // get product with id 1 productsStore.get(1).onsuccess = function(event) { console.log('[Transaction - GET] product with id 1', event.target.result); }; // update product with id 1 products[0].name = 'Blue Men T-shirt'; productsStore.put(products[0]).onsuccess = function(event) { console.log('[Transaction - PUT] product with id 1', event.target.result); }; // delete product with id 2 productsStore.delete(2).onsuccess = function(event) { console.log('[Transaction - DELETE] deleted with id 2'); }; }; request.onerror = function(event) { console.log('[onerror]', request.error); }; request.onupgradeneeded = function(event) { var db = event.target.result; var productsStore = db.createObjectStore('products', {keyPath: 'id'}); };Copy the code

Output:

Inspection Results:

Understand more IndexedDB concepts such as cursors, database migration, and database versioning.

Learning how to use it correctly is a big problem. Follow these tips to make your offline database work better:

  • Static files are cached in the install event of the service worker.
  • It is better to initialize the database in a service activate event than in a worker install event. Mixing the new database with the old service worker can cause conflicts. Use keyPath as the URL store.
  • Whether online or offline, your app will use cached files. But requests for data are still made.
  • When an error occurs in an online request, design an offline-API address and enter the service worker to obtain database data.
  • The request starts with/offline-API, then extracts the data from the database using the equivalent of the request keyPath, sets the appropriate header on the response such as Application/JSON and returns the response to the browser. You can use the Response constructor.

Using the above approach, you can build an application that is completely offline. The author is going to write a series of articles covering Progress Web Apps in detail.

This article may have missed something, so go through the documentation.

Unlike the cache API, the IndexedDB API is event-driven rather than Promise based. Use some IndexedDB wrapper libraries that allow you to write promise-based code.

  • localForage (~8KB, promises, good legacy browser support)
  • IDB-keyval (500 byte alternative to localForage, for modern browsers)
  • IDB-promised (~2k, same IndexedDB API, but with promises)
  • Dexie (~16KB, promises, complex queries, secondary indices)
  • PouchDB (~45KB (supports custom builds), synchronization)
  • Lovefield (relational)
  • LokiJS (in-memory)
  • ydn-db (dexie-like, works with WebSQL)