在开发应用程序时,我们通常需要在用户的计算机上存储一些数据。本地存储的重要性不言而喻,它可以允许用户以后再次访问应用程序时恢复其上一次的活动状态。此外,本地存储还可以用于存储用户的个性化设置和首选项,以及离线使用的数据。
Electron 使用 Chromium 浏览器来渲染网页,因此可以利用 Web 浏览器 API(例如localstorage
、sessionstorage
、IndexedDB
等)来实现本地存储,以在 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 操作数据库的简单示例。