最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端数据库 本地离线存储工具 PouchDB 简单入门(以Node.js场景为例)

    正文概述 掘金(maxlespaul)   2020-12-05   1207

    前端数据库 本地离线存储工具 PouchDB 简单入门(以Node.js场景为例)

    前言

    最近在做一个基于 ElectronVue 的桌面应用程序的个人项目,需要在本地存储和展示本地音频文件的索引数据。过程中也是踩坑无数,跟大家分享一下这段经历。

    离线存储工具的选择

    离线存储,实现的方式有很多。最简单的便是我们熟悉的浏览器端离线存储,如 LocalStorageSessionStorage ,又或是 IndexedDBWeb SQL 。 以上四种离线存储在项目中,均可以通过 Electron 渲染进程中的 Chromium 内核来实现。一些轻量级的第三方库,如 ImmortalDB、web-storage-cache对浏览器离线存储做了一些扩展,但这些库的维护情况还是不太让人满意。不过,这其中的localForage也还是让人眼前一亮。

    受限于浏览器内核的环境,以上方法不能很好满足我的需求,于是只能寻找 node.js 端的存储工具,这其中又分两类,一类是js本身实现(如NeDB和PouchDB),另一类则是成熟的数据库软件(如 MySQLMongoDB)。

    按功能和性能来讲,数据库绝对是最优的选择,但不是很符合我的 Electron 应用程序的定位,1、它们体积非常庞大,需要打包进用户的安装包(实现起来有难度,也没几个让普通的用户能够忍受一个小小软件在自己的计算机上装 MySQL);2、功能庞大,杀鸡焉用牛刀?

    于是,不占空间、轻量又方便打包的 NeDBPouchDB 进入了决赛圈。考虑到 NeDB 是明文存储,功能单一,又年久失修。我就果断选择了隔壁 PouchDB

    PouchDB 入门

    我们先来看看 PouchDB 官网 是如何介绍这个产品的:

    PouchDB 在浏览器和 Node.js 环境下都可以运行,轻量便携、上手简单等优点。PouchDB 在浏览器中默认使用 IndexedDB ,若当前环境不支持,则回退到 Web SQL。在 Node.js 环境中则会以特定格式的本地文件存储数据。官方文档的这个部分详细介绍了在不同环境下的工作形式?Adapters。

    前端数据库 本地离线存储工具 PouchDB 简单入门(以Node.js场景为例)

    安装

    官方文档中给出了两种方式,分别是 CDNnpm

    <script src="//cdn.jsdelivr.net/npm/pouchdb@7.2.1/dist/pouchdb.min.js"></script>
    
    npm install --save pouchdb
    

    初始化

    node 环境中引用 pouchdb,通过PouchDB这个构造函数来创建一个数据库实例:

    const PouchDB = require('pouchdb')
    // 创建在根目录下database文件夹下名为my_database的数据库
    const db = new PouchDB('database/my_database')
    

    new PouchDB([name], [options]) 方法接受数据库名称与配置项作为参数(具体配置项参见文档)。name这个参数除了接受名称外,还可以传入远程 CouchDB 数据库地址,比如 const db = new PouchDB('http://pouch-db.com/my-db')

    不过,官方文档对 node 环境下数据库存储位置并未做足够的说明。 在这里指出,在 node 环境下name可以为相对路径绝对路径,如下:

    // 在{root}/database/my_database目录下创建
    const db = new PouchDB('database/my_database')
    // 在C:/Code/test/test_pouchdb目录下创建
    const db2 = new PouchDB('D:/Code/test/test_pouchdb')
    

    基本操作

    数据库最基本的无非就是又快又方便地做 CRUD 。我们来快速实现一下 PouchDB 的基本操作。所有相关操作均可以在其API文档中找到传送门。

    首先,我们需要定义要存储的数据格式:

    const myData = {
      _id: String,
      title: String
    }
    

    其次,最好使用统一的函数去增添数据,因为在 PouchDB 中并没有严格的 schema 。我们使用 db.put(doc, [options], [callback]) 方法添加或修改数据。

    需要指出, PouchDB 除了用传统的 callback ,还支持更主流的 Promiseasync

    // * 使用函数包装 新增数据 的方法
    function addData(title) {
      // 数据格式
      const data = {
        _id: new Date().toISOString(),
        title: text
      }
      // 增改方法
      db.put(data, function cb(err, result) {
        if (err) {
          console.error(err)
        } else {
          console.log(result)
        }
      })
    }
    

    我们使用 addData() 方法创建一个 title'helloPouchDB' 的数据,然后看一看该数据包含些什么:

    addData('helloPouchDB')
    

    回调函数中的 result 返回了新增的状态、数据的 idrev 。数据中除了 title 也有相应的 _id_rev

    // result
    {
      ok: true,
      id: '2020-12-04T12:54:13.638Z',
      rev: '1-a2436e9326998a520a759f2a274e166b'
    }
    // 保存的那个data
    {
      title: 'helloPouchDB',
      _id: '2020-12-04T12:54:13.638Z',
      _rev: '2-565fec0bf70044cc51d24a8379139f8e'
    }
    
    

    需要注意的是,修改数据需要指定当前修改数据项的 _rev (创建的时候默认就有)。 比如这样:

    db.put({
      title: 'Nice to meet you',
      _id: '2020-12-04T12:54:13.638Z',
      _rev: '2-565fec0bf70044cc51d24a8379139f8e'
    })
    

    从数据库中根据id查找(fetch)数据,需要用到 db.get(docId, [options], [callback]),如 db.get(_id)。配置项中可以指定一个或者多个 rev,其他的配置项参考文档。

    如果需要获取多条数据,则需要使用 db.allDocs([options], [callback]) (文档传送门)。在配置项中可以指定 skiplimit 来实现分页功能。

    function showData() {
      db.allDocs({
        include_docs: true, // 返回的数据中默认只有id和rev,带上数据需传true
        descending: true, // 降序排列
        skip: 20,// 第3页
        limit: 10 // 每页10条
      })
        .then((res) => {
          console.log(res)
        })
        .catch((err) => {
          console.error(err)
        })
    }
    

    返回的数据,包含了总条数 total_rows 、跳过的条数 offset 、与数据的数组 rows 。格式如下:

    {
      total_rows: 1,
      offset: 0,
      rows: [
        {
          id: '2020-12-04T13:00:26.358Z',
          key: '2020-12-04T13:00:26.358Z',
          value: { rev: '1-6da27cff722c24cfe38fb09be78f8576' },
          doc: {
            title: 'helloPouchDB',
            _id: '2020-12-04T13:00:26.358Z',
            _rev: '1-6da27cff722c24cfe38fb09be78f8576'
          }
        }
      ]
    }
    

    接下来是最重要的一个查询方法 db.find(request [, callback]) 。这个方法允许通过数据的字段来查询数据 文档传送门。需要注意,这个方法需要引入 pouchdb-find 插件

    # 安装
    npm install --save pouchdb-find
    
    const PouchDB = require('pouchdb')
    // 注入插件
    PouchDB.plugin(require('pouchdb-find'))
    

    db.find() 通过 selector 指定查询内容、 fields 指定返回的内容包含的字段。 selector 也可以使用 $lt$gt 等过滤器指定特殊的查询条件。与 db.allDocs() 一样,可以指定 skiplimit

    db.find({
      selector: {
        title: 'helloPouchDB',
      },
      fields: ['_id', 'name'],
    })
    

    改、删

    结合 新增查询 这两种方法, 我们变可以获取已有的数据并使用 db.put() 方法对其进行修改:

    // 查询
    db.find({
      selector: {
        title: 'helloPouchDB',
      },
    })
      .then((res) => {
      // 获取该数据
        const result = res.docs[0]
        // 修改数据
        result.title = 'Nice to meet you'
        // 修改并写入
        db.put(result)
          .then((res) => {
            console.log('yes!')
          })
          .catch((err) => {
            console.error(err)
          })
      })
      .catch((err) => {
        console.error(err)
      })
    

    删除数据 可以通过 db.remove(doc, [options], [callback]) 方法,该方法除了接受 doc 对象外,也可以通过 idrev 删除数据。

    // 方式1 - 获取实例并删除
    db.get(_id, function(err, doc) {
      if (err) { return console.log(err) }
      db.remove(doc, function(err, response) {
        if (err) { return console.log(err) }
      })
    })
    // 方式2 - 通过 id 和 rev 删除
    db.remove(doc._id, doc._rev, function(err, response) {
        if (err) { return console.log(err) }
      })
    })
    

    起源地下载网 » 前端数据库 本地离线存储工具 PouchDB 简单入门(以Node.js场景为例)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元