lowdb 在electron 使用中注意的問題


前言

可能很多人都沒有聽說過這個lowdb,但是它的確存在,而且在electron 中用到還是挺多的。

如何在electron 的render 進程中是引用electron 模塊。

我們知道一個問題,那就是app 模塊是main 進程中特有的那么,render 進程中要使用必須這樣:import { app, remote } from 'electron' // 引入remote模塊

然后remote.app 這樣使用即可。

所以我們在render中使用lowdb可以這樣使用:

import Datastore from 'lowdb'

import FileSync from 'lowdb/adapters/FileSync'

import path from 'path'

import fs from 'fs-extra'

import { app, remote } from 'electron' // 引入remote模塊

const APP = process.type === 'renderer' ? remote.app : app // 根據process.type來分辨在哪種模式使用哪種模塊

const STORE_PATH = APP.getPath('userData') // 獲取electron應用的用戶目錄

const adapter = new FileSync(path.join(STORE_PATH, '/data.json')) // 初始化lowdb讀寫的json文件名以及存儲路徑

const db = Datastore(adapter) // lowdb接管該文件

export default db // 暴露出去

開發模式和生產模式初始化路徑問題

在開發模式的時候,通過 APP.getPath('userData') 獲取到的路徑形如: /Users/molunerfinn/Library/Application Support/Electron (macOS下)。這個是一個已經自動創建好的路徑。所以在開發模式的時候,初始化路徑是已經存在的。

然而在生產模式下不是這樣。生產模式下,第一次打開應用的過程中, APP.getPath('userData') 獲取的路徑並未創建,而 datastore.js 卻已經被加載。所以這個時候初始化路徑並不存在。

所以我們必須在 datastore.js 里做一次路徑是否存在的判斷:

此處的fs是來自fs-extra模塊

if (process.type !== 'renderer') {
    if (!fs.pathExistsSync(STORE_PATH)) { // 如果不存在路徑
    fs.mkdirpSync(STORE_PATH) // 就創建
  }
}

唯一標識的id字段

用過MySQL的人大多都會在表里初始化一個自增的id字段作為數據的唯一標識。而lowdb雖然無法很方便地創建一個自增的id字段,但是通過 lodash-id 這個插件可以很方便地為每個新增的數據自動加上一個唯一標識的id字段。

{
  "height": 514,
  "type": "weibo",
  "width": 514,
  "id": "7f247aa7-ffeb-4bb1-87f1-a0d69824ec78"
}

初始化也很方便:

import LodashId from 'lodash-id'
const db = Datastore(adapter)
db._.mixin(LodashId) // 通過._mixin()引入

初始化完整代碼

通過上述的踩坑,PicGo的初始化代碼如下,僅供參考:

import Datastore from 'lowdb'
import LodashId from 'lodash-id'
import FileSync from 'lowdb/adapters/FileSync'
import path from 'path'
import fs from 'fs-extra'
import { remote, app } from 'electron'

const APP = process.type === 'renderer' ? remote.app : app
const STORE_PATH = APP.getPath('userData')

if (process.type !== 'renderer') {
  if (!fs.pathExistsSync(STORE_PATH)) {
    fs.mkdirpSync(STORE_PATH)
  }
}

const adapter = new FileSync(path.join(STORE_PATH, '/data.json'))

const db = Datastore(adapter)
db._.mixin(LodashId)

if (!db.has('uploaded').value()) {
  db.set('uploaded', []).write()
}

if (!db.has('picBed').value()) {
  db.set('picBed', {
    current: 'weibo'
  }).write()
}

if (!db.has('shortKey').value()) {
  db.set('shortKey', {
    upload: 'CommandOrControl+Shift+P'
  }).write()
}

export default db

不同進程讀取的數據不一致。

lowdb在使用的過程中會遇到一個大坑在於,如果就按照基本操作,那么有可能出現我在 main 進程里存入的值,在 renderer 進程里讀不到。

為啥?因為直接引用的 db 實際上只是那個時刻在內存里的數據。lowdb在使用過程中會把JSON數據讀入內存中。只有在需要寫操作的時候才會將新的數據寫入磁盤。

db.read().get('xxx').value()

db.read().set('xxx', 'xxx')

為了避免這么麻煩呢,最后是前端的db傳遞給后端處理最為合適,不要搞兩套。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM