浏览器缓存优化——indexDB

浏览器缓存优化——indexDB

前言

开发大型项目,缓存数据非常大,localStorage最多也就5M的存储量,显然支撑不了。对于3D可视化项目,资源要达到几M甚至是几十M,如果全部放在服务器,每次加载都从服务器读取速度非常慢,能不能缓存在浏览器提升用户体验呢。

针对以上问题 indexDB 顺势而生,缓存容量无上限。

IndexDB介绍

打开控制台,既可看到IndexDB,它的存储方式更像树mysql的数据表,也有主键
在这里插入图片描述

如何操作IndexDB

话不多说直接上代码,这里代码是以封装的形式,大家可以放在本地使用,也可以根据需要打包成类库

类库代码
// 浏览器缓存 indexDB

/**
 * dbName 数据库名
 * storeName 表名
 * indexList 索引列表
 */

/* 打开数据库 */
export function openDB(dbName, storeName, version = 1, indexList = []) {
    return new Promise((resolve, reject) => {
        let indexedDB = window.indexedDB
        let db
        const request = indexedDB.open(dbName, version)
        request.onsuccess = function (event) {
            db = event.target.result
            resolve(db)
        }
        request.onerror = function (event) {
            reject(event)
        }
        // 数据库创建或升级的时候会触发
        request.onupgradeneeded = (e) => {
            db = event.target.result
            let objectStore
            if (!db.objectStoreNames.contains(storeName)) {
                objectStore = db.createObjectStore(storeName, { keyPath: 'id' })//设置主键
                //添加自定义索引
                if (indexList.length) {
                    indexList.forEach(item => {
                        objectStore.createIndex(item, item, { unique: false })//索引值可能会重复,所以设为false
                    })
                }

            }

        }
    })

}

/* 新增数据 */
export function addData(db, storeName, data) {
    return new Promise((resolve, reject) => {
        const request = db.transaction([storeName], 'readwrite')// 事务对象 指定表格名称和操作模式("只读"或"读写")
            .objectStore(storeName)
            .add(data)

        request.onsuccess = (e) => {
            resolve(e)
        }
        request.onerror = (e) => {
            throw new Error(e.target.error)
        }
    })
}

/**
 * 通过主键读取数据
 */
export function getDataByKey(db, storeName, key) {
    return new Promise((resolve, reject) => {
        const request = db.transaction([storeName])
            .objectStore(storeName)
            .get(key)
        request.onsuccess = (e) => {
            resolve(e.result)
        }
        request.onerror = (e) => {
            throw new Error(e.target.error)
        }
    })
}

/* 通过游标读取数据 */
export function cursorGetData(db, storeName) {
    let list = []
    const request = db.transaction([storeName], 'readwrite')
        .objectStore(storeName)
        .openCursor()
    return new Promise((resolve, reject) => {
        request.onsuccess = (e) => {
            let cursor = e.target.result
            if (cursor) {
                list.push(cursor.value)
                cursor.continue() //遍历存储对象中所有内容
            } else {
                resolve(list)
            }
        }
        request.onerror = (e) => {
            reject(e)
        }
    })
}
/* 通过索引读取数据 */
export function getDataByIndex(db, storeName, indexName, indexValue) {
    const request = db.transaction([storeName], 'readwrite')
        .objectStore(storeName)
        .index(indexName)
        .get(indexValue)

    return new Promise((resolve, reject) => {
        request.onerror = function (e) {
            reject(e)
        }
        request.onsuccess = function (e) {
            resolve(e.target.result)
        }
    })
}
/**
 * 通过索引和游标查询记录
 */
export function cursorGetDataByIndex(db, storeName, indexName, indexValue) {
    let list = []
    const request = db.transaction(storeName, 'readwrite').objectStore(storeName) // 仓库对象
        .index(indexName) // 索引对象
        .openCursor(IDBKeyRange.only(indexValue)) // 指针对象
    return new Promise((resolve, reject) => {
        request.onsuccess = function (e) {
            let cursor = e.target.result
            if (cursor) {
                list.push(cursor.value)
                cursor.continue() // 遍历了存储对象中的所有内容
            } else {
                resolve(list)
            }
        }
        request.onerror = function (ev) {
            reject(ev)
        }
    })
}
/* 更新数据 -- 没有则添加 */
export function updateDB(db, storeName, data) {
    const request = db.transaction([storeName], 'readwrite')
        .objectStore(storeName)
        .put(data)
    return new Promise((resolve, reject) => {
        request.onsuccess = (ev) => {
            resolve(ev)
        }
        request.onerror = (ev) => {
            reject(ev)
        }
    })
}
/* 通过id 删除数据 */
export function deleteDB(db, storeName, id) {
    const request = db.transaction([storeName], 'readwrite')
        .objectStore(storeName)
        .delete(id)
    return new Promise((resolve, reject) => {
        request.onsuccess = (ev) => {
            resolve(ev)
        }
        request.onerror = (ev) => {
            reject(ev)
        }
    })
}
/**
 * 删除数据库
 */
export function deleteDBAll(dbName) {
    let deleteRequest = window.indexedDB.deleteDatabase(dbName)
    return new Promise((resolve, reject) => {
        deleteRequest.onerror = function (event) {
            reject('删除失败')
        }
        deleteRequest.onsuccess = function (event) {
            resolve('删除成功')
        }
    })
}
/**
 * 关闭数据库
 */
export function closeDB(db) {
    db.close()
}
export default {
    openDB,
    addData,
    getDataByKey,
    cursorGetData,
    getDataByIndex,
    cursorGetDataByIndex,
    updateDB,
    deleteDB,
    deleteDBAll,
    closeDB
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端性能优化实践# 知识体系与小册格局 ## 写给读者 提起性能优化,大家现在脑海里第一时间会映射出什么内容呢? 可能是类似[“雅虎军规”](https://developer.yahoo.com/performance/rules.html?guccounter=1)和[《高性能 JavaScript》](https://book.douban.com/subject/5362856/)这样历久弥香的经典之作,也可能是搜索引擎聚合给你的一篇又一篇以性能优化为主题的个人或团队实践而来的“私货”。至少当我确定自己的研发方向、并接到第一个性能优化任务时,我做的第一件事是向搜索引擎求助,第二件事是买书,然后开始了摸着石头过河,前后花费了大量的时间和精力。我深感性能优化实在是前端知识树中特别的一环——当你需要学习前端框架时,文档和源码几乎可以告诉你所有问题的答案,当你需要学习 Git 时,你也可以找到放之四海皆准的实践方案。但性能优化却不一样,它好像只能是一个摸索的过程。 这个摸索的过程是痛苦的、漫长的,也是紧要的。因为在如今的互联网环境下,一个前端团队如果只把性能优化这个任务写在纸上,而不投入实践,它将缺失最基本的竞争力。 笔者写这本小册,是希望通过短短十数个章节的讲解,尽可能降低一些大家学习性能优化的成本。 一方面,这本小册为没有接触过性能优化的新同学建立起一个正确的前端性能优化的“世界观”,知道性能优化是什么、为什么、怎么做,从而使性能优化这件事情有迹可循,有路可走。这样在面试现场被问到性能优化层面的问题时,能够做到滔滔不绝、言之有物,而非像背书一样罗列干巴巴的知识点,最终淹没在茫茫的求职大军中。另一方面,小册可以为在职的工程师们提供一线团队已经实践过的“方法论”,知道什么场景下该做什么事情,最终在脑海中留下一张涵盖核心原理和实践的、可随时查阅并且高度可扩展的性能优化思路索引表。然后在今后的开发生活中可以去践行它,更进一步去挖掘它。把性能优化变作你前端工程师生涯的一门必修课,进而演化为自己研发方面的核心竞争力。 同时,相信大家可以明确这样一个学习观念:任何技术的掌握,都离不开一定比例的理论基础和实际操作的支撑。 具体到前端性能优化这件事情上,我认为它是 20% 的理论,加上至少 80% 的实践,甚至很多理论本身也都是我们在具体的业务场景中实践出来的。所以希望大家阅读本小册时,能够读到一些“书本之外的东西”——最好是一边读一边回忆自己既有的开发经历,尝试去留意哪些知识是已知的,哪些是未知的。 这样读完之后,就可以有的放矢地把这些知识转换为自己的项目实践——前端技术日新月异,性能方案永远都在更迭,所以一定要形成自己的学习思路。 建议每一位读者都带着“学了就要用”的心态去读这本小册。如果阅读结束,能够为你带来哪怕一个小小的开发习惯或者优化观念上的改变,这数小时的阅读时间就算没有白费。 ## 知识体系: 从一道面试题说起 在展开性能优化的话题之前,我想先抛出一个老生常谈的面试问题: > 从输入 URL 到页面加载完成,发生了什么? 这个问题非常重要,因为我们后续的内容都将以这个问题的答案为骨架展开。我希望正在阅读这本小册的各位可以在心里琢磨一下这个问题——无须你调动太多计算机的专业知识,只需要你用最快的速度在脑海中架构起这个抽象的过程——我们接下来所有的工作,就是围绕这个过程来做文章。 我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛出我们的 HTTP 请求,服务端处理完我们的请求之后,把目标数据放在 HTTP 响应里返回给客户端,拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕,页面便呈现给了用户,并时刻等待响应用户的操作(如下图所示)。 ![](https://user-gold-cdn.xitu.io/2018/10/18/16685737b823244c?w=489&h=329&f=png&s=19023) 我们将这个过程切分为如下的过程片段: 1. DNS 解析 2. TCP 连接 3. HTTP 请求抛出 4. 服务端处理请求,HTTP 响应返回 5. 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户 大家谨记,我们任何一个用户端的产品,都需要把这 5 个过程滴水不漏地考虑到自己的性能优化方案内、反复权衡,从而打磨出用户满意的速度。 ## 从原理到实践:各个击破 我们接下来要做的事情,就是针对这五个过程进行分解,各个提问,各个击破。 具体来说,DNS 解析花时间,能不能尽量减少解析次数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值