引言
在JS开发过程中,我们常常会用到 async/await的写法,来实现异步编程,但是这样的操作也会产生并发编程的常见问题。在后端处理上,我们会使用共享内存的lock锁机制,CSP/Actor机制等常见的类库方案,也会使用sqlite、mysql、redis这些具备transaction(事务)特性的数据库来实现消息队列。而此次在Browser前端开发中,我尝试用IndexedDB来实现对async/await的解决方案。
什么是IndexedDB
在浏览器中,我们更多接触到的是Cookie和LocalStorage。
在mdn中是这样介绍:
IndexedDB 是一个事务型数据库系统,类似于基于 SQL 的 RDBMS。然而,不像 RDBMS 使用固定列表,IndexedDB 是一个基于 JavaScript 的面向对象数据库。IndexedDB 允许您存储和检索用键索引的对象;可以存储结构化克隆算法支持的任何对象。您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务。
如何使用IndexedDB
IndexedDB版本支持情况
玩前端的都知道浏览器种类繁多,什么chrome系,webkit系,firefox系等。这里我建议使用JS库——jakearchibald/idb
引用
Using npm
$ npm install idb
// demo.js
import { openDB, deleteDB, wrap, unwrap } from 'idb';
async function doDatabaseStuff() {
const db = await openDB(…);
}
Using browser
-
modules 写法
<script type="module"> import { openDB, deleteDB, wrap, unwrap } from 'https://cdn.jsdelivr.net/npm/idb@7/+esm'; async function doDatabaseStuff() { const db = await openDB(…); } </script> -
外部引用
<script src="https://cdn.jsdelivr.net/npm/idb@7/build/umd.js"></script> <script> async function doDatabaseStuff() { const db = await idb.openDB(…); } </script>
基本操作
检测IndexedDB API是否生效
(() => {
'use strict'
if (!('indexedDB' in window)) {
console.warn('IndexedDB not supported')
return
}
//...IndexedDB code
})()
连接DB
(async () => {
//...
const dbName = 'mydbname'
const storeName = 'store1'
const version = 1 //versions start at 1
const db = await openDB(dbName, version, {
upgrade(db, oldVersion, newVersion, transaction) {
const store = db.createObjectStore(storeName)
}
})
})()
创建数据
(async () => {
//...
const dbName = 'mydbname'
const storeName = 'store0'
const version = 1
const db = await openDB(dbName, version,{
upgrade(db, oldVersion, newVersion, transaction) {
const store = db.createObjectStore(storeName)
store.put('Hello world!', 'Hello')
}
})
})()
带事务创建数据
(async () => {
//...
const dbName = 'mydbname'
const storeName = 'store0'
const version = 1
const db = await openDB(/* ... */)
const tx = db.transaction(storeName, 'readwrite')
const store = await tx.objectStore(storeName)
const val = 'hey!'
const key = 'Hello again'
const value = await store.put(val, key)
await tx.done
})()
根据 Key 读取数据
const key = 'Hello again'
const item = await db.transaction(storeName).objectStore(storeName).get(key)
读取所有keys数据
const items = await db.transaction(storeName).objectStore(storeName).getAllKeys()
读取所有values数据
const items = await db.transaction(storeName).objectStore(storeName).getAll()
删除数据库
const dbName = 'mydbname'
await deleteDB(dbName)
根据 Key 删除数据
(async () => {
//...
const dbName = 'mydbname'
const storeName = 'store1'
const version = 1
const db = await openDB(dbName, version, {
upgrade(db, oldVersion, newVersion, transaction) {
const store = db.createObjectStore(storeName)
}
})
const tx = await db.transaction(storeName, 'readwrite')
const store = await tx.objectStore(storeName)
const key = 'Hello again'
await store.delete(key)
await tx.done
})()
清除数据
await store.clear();
引用 A quick but complete guide to IndexedDB and storing data in browsers