HTML5 -- 浏览器数据缓存 -- indexedDB

简介: IndexedDB是一种可以让你在用户的浏览器内持久化存储数据的方法,为web应用提供了丰富的查询功能,使我们的应用在在线和离线都能正常工作。由于 IndexedDB 本身的规范还在持续演进中,当前的 IndexedDB 的实现还是使用浏览器前缀。

IndexedDB是一种可以让你在用户的浏览器内持久化存储数据的方法,为web应用提供了丰富的查询功能,使我们的应用在在线和离线都能正常工作。

由于 IndexedDB 本身的规范还在持续演进中,当前的 IndexedDB 的实现还是使用浏览器前缀。在规范更加稳定之前,浏览器厂商对于标准 IndexedDB API 可能都会有不同的实现。但是一旦大家对规范达成共识的话,厂商就会不带前缀标记地进行实现。实际上一些实现已经移除了浏览器前缀:IE 10,Firefox 16 和 Chrome 24。

如果你希望在仍旧使用前缀的浏览器中测试你的代码, 可以使用下列代码:

window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange

要注意的是使用前缀的实现可能会有问题,或者是实现的并不完整,也可能遵循的还是旧版的规范。因此不建议在生产环境中使用。我们更倾向于明确的不支持某一浏览器,而不是声称支持但是实际运行中却出问题:

function hasIndexedDB () {
   if (!window.indexedDB) {
      return true;
   }
}

打开数据库:

// 打开我们的数据库
var request = window.indexedDB.open("MyTestDatabase");

indexedDB打开数据库的方法如上,必须进行request,indexedDB只有一个open方法,上面的代码表示打开了一个"MyTestDatabase"的数据库,该方法可以接受第二个参数:

// 打开我们的数据库,版本号为1
var request = window.indexedDB.open("MyTestDatabase", 1);

第二个参数的版本号为整数,当前打开的版本号不能比现有的版本号小,否则会报错。

几乎所有我们产生的请求我们在处理的时候首先要做的就是添加成功和失败处理函数:

var db;
request.onerror = function(event) { // Do something with request.errorCode! }; request.onsuccess = function(event) {
  db = event.target.result;
// Do something with request.result! };

request还有一个回掉方法:

request.onupgradeneeded = function(event) {
  var _db = event.target.result;
  // Do something with request.result!
};

onupgradeneeded方法是只有在版本号升级的情况下才会执行(如果当前版本号为1,当我们在打开open(storeName, 2)时,onupgradeneeded就会执行)。

下面是整个数据库的操作流程:

当我们创建一个新的数据表时,我们首先要在onupgradeneeded方法中创建表:

// 只有在onupgradeneeded方法中有效
var createObjectStore = function (db, storeName) {
if (!db.objectStoreNames.contains(storeName)) { db.createObjectStore(storeName, { keyPath: 'id', autoIncrement: true }) console.log("createObjectStore:" + storeName + ",成功!") } }

删除表:

// 删除Store(在onupgradeneeded里调用)
deleteObjectStore (db, storeName) {
    console.log('deleteObjectStore')
    if (db.objectStoreNames.contains(storeName)) {
      db.deleteObjectStore(storeName)
      console.log("deleteObjectStore:" + storeName + ",成功!")
    }
}

表中添加数据:

var students: [
        { id: 1001, name: "Byron", age: 24 }, 
        { id: 1002, name: "Frank", age: 30 }, 
        { id: 1003, name: "Aaron", age: 26 }, 
        { id: 1004, name: "Casper", age: 26 }
]
// 添加数据方法 在onsuccess中执行
var addData = function (db, storeName) {
    console.log('addData success')
    let transaction = db.transaction(storeName, 'readwrite')
    let store = transaction.objectStore(storeName)
    let request = null

    for (let i = 0; i < students.length; i++) {
      request = store.add(tstudents[i])
      request.onerror = function () {
        console.error('数据库已有该数据!')
      } 
      request.onsuccess = function () {
        console.log('添加成功')
      }
    }
}

注意,在执行addData方法的时候,要确保已执行createObjectStore方法,否则会报错。添加完之后浏览器显示:

 

查询数据:

  // 查询数据(根据关键词keyValue)
  var getDataByKey = function (db, storeName, keyValue) {
    let transaction = db.transaction(storeName, 'readonly')
    let store = transaction.objectStore(storeName)

    let request = store.get(keyValue)
    request.onsuccess = function (e) {
      let result = e.target.result
      console.log(result)
    }
  }

 更新数据:

  // 更新数据
  var updateDataByKey = function (db, storeName, keyValue) {
    let transaction = db.transaction(storeName, 'readwrite')
    let store = transaction.objectStore(storeName)
    let request = store.get(keyValue)
    request.onsuccess = function (e) {
      let student = e.target.result
      student.age = 35
      store.put(student)
      console.log(student)
    }
  }

删除数据:

  // 删除数据
  var deleteDataByKey = function (db, storeName, keyValue) {
    let transaction = db.transaction(storeName, 'readwrite')
    let store = transaction.objectStore(storeName)
    let result = store.delete(keyValue)
    result.onsuccess = function () {
      console.log('删除成功')
    }
    result.onerror = function () {
      console.log('删除失败')
    }
  }

清空表:

  // 清空store
  var clearObjectStore = function (db, storeName) {
    let transaction = db.transaction(storeName, 'readwrite')
    let store = transaction.objectStore(storeName)
    let request = store.clear()
    request.onsuccess = function () {
      console.log('清空成功')
    }
    request.onerror = function () {
      console.log('清空失败')
    }
  }

关闭数据库:

  // 关闭database
  var closeIDB = function (db) {
    db.close()
    console.log('关闭')
  }

删除数据库:

  // 删除database
  var deleteIDB = function (db) {
    console.log('删除')
    window.indexedDB.deleteDatabase(db)
  }

新增表(带索引):

  // 新增Store--带索引(在onupgradeneeded里调用)
  var createObjectStoreWidthIndex = function (db, storeName) {
    if (!db.objectStoreNames.contains(storeName)) {
      let store = db.createObjectStore(storeName, {
        keyPath: 'id'
      })
      store.createIndex('nameIndex', 'name', {
        unique: true
      })
      store.createIndex('ageIndex', 'age', {
        unique: false
      })
      console.log("createObjectStore:" + storeName + ",成功!")
    }
  }

成功之后浏览器端显示:

获取数据的方法:

  // 获取数据(根据索引)
  var getDataByIndex = function (db, storeName) {
    let transaction = db.transaction(storeName, 'readonly')
    let store = transaction.objectStore(storeName)
    let index = store.index('nameIndex')
    index.get('Byron').onsuccess = function (e) {
      let student = e.target.result
      console.log(student)
    }
  }
  // 使用游标
  var fetchStoreByCursor = function (db, storeName) {
    let transaction = db.transaction(storeName)
    let store = transaction.objectStore(storeName)
    let request = store.openCursor() // 查询全部
    request.onsuccess = function (e) {
      let cursor = e.target.result
      if (cursor) {
        let student = cursor.value
        console.log(student)
        cursor.continue()
      }
    }
  }
  // 索引与游标结合
  var getDataByMultiple = function (db, storeName) {
    // 指定游标范围
    // IDBKeyRange.only(value):只获取指定数据
    // IDBKeyRange.lowerBound(value,isOpen):获取比value大的数据(isOpen: true不包含value, false包含value)
    // IDBKeyRange.upperBound(value,isOpen):获取比value小的数据(isOpen: true不包含value, false包含value)
    // IDBKeyRange.bound(value1,value2,isOpen1,isOpen2)
    let transaction = db.transaction(storeName)
    let store = transaction.objectStore(storeName)
    let index = store.index('ageIndex')
    index.openCursor(IDBKeyRange.bound(24, 30, true, true)).onsuccess = function (e) {
      let cursor = e.target.result
      if (cursor) {
        let s = cursor.value
        console.log(s)
        cursor.continue()
      }
    }
  }

如果我们需要手动更新版本,我们先要将indexedDB关闭,然后再打开新版本的数据库:

  var updataVersion = function (db, storeName, version) {
    closeIDB(db)
    console.log('更新版本', storeName, version)
    openIDB(storeName, version)
  }

 

每一次的记录,都是向前迈进的一步
目录
相关文章
|
3月前
|
Web App开发 存储 缓存
如何精准清除特定类型或标签的缓存数据?
如何精准清除特定类型或标签的缓存数据?
305 57
|
5月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
存储 缓存 监控
一次缓存引发的文件系统数据不一致问题排查与深度解析
本文详述了一次由自研分布式文件系统客户端 EFC 的缓存架构更新所引发的严重数据不一致问题的完整排查过程。
一次缓存引发的文件系统数据不一致问题排查与深度解析
|
5月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
186 32
|
6月前
|
Web App开发 前端开发 JavaScript
如何模拟浏览器行为获取网页中的隐藏表单数据?
如何模拟浏览器行为获取网页中的隐藏表单数据?
|
7月前
|
机器学习/深度学习 人工智能 缓存
MHA2MLA:0.3%数据微调!复旦团队开源推理加速神器,KV缓存狂降96.87%
MHA2MLA是复旦大学、华东师范大学、上海AI Lab等机构联合推出的数据高效微调方法,通过引入多头潜在注意力机制(MLA),显著优化基于Transformer的LLM推理效率,降低推理成本。
216 1
MHA2MLA:0.3%数据微调!复旦团队开源推理加速神器,KV缓存狂降96.87%
|
8月前
|
存储 缓存 JSON
浏览器的缓存方式几种
浏览器缓存方式主要包括:1. **强制缓存**,通过 `Expires` 或 `Cache-Control` 控制,缓存有效期内不发起请求;2. **协商缓存**,使用 `ETag` 和 `Last-Modified` 判断资源是否更新;3. **Service Worker 缓存**,适用于 PWA 应用,拦截并返回缓存;4. **浏览器存储**,如 LocalStorage、SessionStorage 和 IndexedDB,用于持久化或会话级数据存储;5. **Push Cache**,仅限 HTTP/2,服务器主动推送资源。选择合适的缓存策略可优化性能和用户体验。
236 16
|
11月前
|
缓存 监控 测试技术
如何利用浏览器的缓存来优化网站性能?
【10月更文挑战第23天】通过以上多种方法合理利用浏览器缓存,可以显著提高网站的性能,减少网络请求,加快资源加载速度,提升用户的访问体验。同时,要根据网站的具体情况和资源的特点,不断优化和调整缓存策略,以适应不断变化的业务需求和用户访问模式。
584 63
|
11月前
|
Web App开发 缓存 UED
如何设置浏览器的缓存策略?
【10月更文挑战第23天】通过合理地设置浏览器的缓存策略,可以在提高网页性能、减少网络流量的同时,确保用户能够获取到最新的内容,从而提升用户体验和网站的性能优化效果。
888 60
|
11月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
196 5