多多读书
1029 字
5 分钟
Electron开发实践四,本地存储方案选型

在开发应用程序时,我们通常需要在用户的计算机上存储一些数据。本地存储的重要性不言而喻,它可以允许用户以后再次访问应用程序时恢复其上一次的活动状态。此外,本地存储还可以用于存储用户的个性化设置和首选项,以及离线使用的数据。

Electron 使用 Chromium 浏览器来渲染网页,因此可以利用 Web 浏览器 API(例如localstoragesessionstorageIndexedDB等)来实现本地存储,以在 Electron 应用程序中存储和访问用户数据。此外,Electron 还可以利用 Node.js 的文件系统模块对文件系统进行操作,包括读取、写入、删除和复制等操作。同时,Electron 还支持多种数据库技术,如 SQLite 和 LevelDB,以实现更高效的大量结构化数据处理。然而,在实际开发中,选择哪种 Electron 本地存储方式?接下来,我将分析在开发 ChatGPT 应用中选择的方式。

少量简单数据#

对于一些简单少量的键值对数据,比如在开发 ChatGPT 应用时需要配置秘钥、模型等,许多人可能会选择使用localstorage来存储这些数据。然而,在实际使用中发现localstorage有一个问题,即在更新软件并覆盖安装后会导致数据丢失。为了解决这个问题,在开发中我们采用了localForage库来进行数据存储。localForage库内部首选使用IndexedDB来存储数据,因此在更新软件并覆盖安装时不会丢失数据。此外,localForage库的 API 与localstorage相似,因此非常容易上手。

通过 npm 安装:

npm install localforage

localForage提供回调 API 同时也支持 ES6 Promises API,你可以自行选择。

localforage
  .getItem('somekey')
  .then(function (value) {
    // 当离线仓库中的值被载入时,此处代码运行
    console.log(value)
  })
  .catch(function (err) {
    // 当出错时,此处代码运行
    console.log(err)
  })

// 回调版本:
localforage.getItem('somekey', function (err, value) {
  // 当离线仓库中的值被载入时,此处代码运行
  console.log(value)
})

其他一些 API 调用与localstorage类型,不再赘述。另外一些教程会推荐electron-store,也是一个对简单数据的存储方式,这个库是通过在应用本地创建 JSON 文件实现持久化保存的。

大量结构化数据#

对于用户聊天数据这种需要处理大量数据并根据条件查询的情况,使用 IndexedDB或数据库是更合适的选择。而数据库选择通常采用 SQLite,SQLite 是一种嵌入式数据库,可以直接将数据库文件嵌入到 Electron 应用中,不需要单独运行一个数据库服务器。

在这个 ChatGPT 应用中采用了 SQLite,原因是 SQLite 提供了更丰富的查询语言和功能,适合复杂的数据结构和高级查询需求。另外使用 Knex.js 作为数据处理和查询的工具,可以进一步简化和优化数据库操作。Knex.js 是一个基于 Promise 的查询构建器,它提供了一套易于使用且可扩展的 API,可以通过链式调用来构建复杂的数据库查询。

使用前,先安装依赖:

npm i sqlite3 knex

创建数据库:

function configureDatabase() {
  // 获取用户数据目录的路径
  const userDataPath = app.getPath('userData')
  // 构建数据库文件的完整路径
  const dbPath = path.join(userDataPath, 'local.db')
  // 使用knex库创建一个数据库连接
  return knex({
    client: 'sqlite3',
    connection: {
      filename: dbPath,
    },
    useNullAsDefault: true,
  })
}

初始化数据库表:

async function initTableConversations(knex: any) {
  // 判断表conversations是否存在
  const exists = await knex.schema.hasTable('conversations')
  if (!exists) {
    // 创建表并初始化字段
    await knex.schema.createTable('conversations', function (table: any) {
      table.increments('id').primary()
      table.string('title')
      table.json('conversations')
      table.integer('created_at').defaultTo(Date.now())
    })
  }
}

导出数据库连接:

// database.ts
export default (async function setupDatabase() {
  try {
    // 初始化调用
    const knex = configureDatabase()
    await initTableConversations(knex)
    return knex
  } catch (error) {
    throw error
  }
})()

查询数据:

import database from './database'

database.then((db) => db.select('id', 'title'))

删除数据:

database.then((db) => db.delete().from('conversations').where('id', id))

以上是使用 knex 操作数据库的简单示例。

Electron开发实践四,本地存储方案选型
https://fuwari.vercel.app/posts/20231219/
作者
我也困了
发布于
2023-12-19
许可协议
CC BY-NC-SA 4.0