• 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传递给后端处理最为合适,不要搞两套。

  • 相关阅读:
    HDU-统计难题
    POJ-A Simple Problem with Integers
    HDU-I Hate It
    个人站立会议06
    个人站立会议05
    个人站立会议04
    易校小程序典型用户需求分析
    个人站立会议03
    个人第二次晚间站立总结会议
    个人站立会议02
  • 原文地址:https://www.cnblogs.com/aoximin/p/13152003.html
Copyright © 2020-2023  润新知