Electron中正确导入Node模块:集成lmdb库报错求助
Electron集成lmdb库报错:Uncaught TypeError: open is not a function
我是Electron新手,正尝试在Electron中集成npm的lmdb库,但操作方式可能有误,特此求助。我使用preload.js、main.js和renderer.js,相关代码如下:
现有代码
preload.js
const { contextBridge } = require('electron') contextBridge.exposeInMainWorld('versions', { node: () => process.versions.node, chrome: () => process.versions.chrome, electron: () => process.versions.electron, lmdb: () => process.lmdb // we can also expose variables, not just functions })
main.js
const { app, BrowserWindow } = require('electron') const path = require('path') function createWindow () { const win = new BrowserWindow({ width: 1200, height: 800, autoHideMenuBar: true, // resizable: false, icon: path.join(__dirname, 'gigatreelogosvv.ico'), // autoHideMenuBar: true, webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: true, contextIsolation: true } }) win.loadFile('index.html') win.webContents.openDevTools() }
renderer.js
const open = versions.lmdb.open; let blocks = open({ path: "./db/blocks", compression: true, });
控制台报错信息
Uncaught TypeError: open is not a function at renderer.js:8:14
问题原因
- preload.js暴露逻辑错误:你写的
lmdb: () => process.lmdb里,process对象根本不存在lmdb属性,而且这里暴露的是一个函数,不是lmdb模块本身。渲染进程中versions.lmdb是函数而非包含open方法的对象,自然会触发报错。 - 模块使用规范不符:lmdb是Node.js模块,在Electron开启上下文隔离(
contextIsolation: true)的情况下,渲染进程不能直接访问Node.js模块,需要通过预加载脚本安全暴露,或在主进程处理数据库操作后通过IPC供渲染进程调用。
修复方案
步骤1:安装lmdb
确保项目已安装依赖:
npm install lmdb
方案A:预加载脚本直接暴露lmdb方法
修改preload.js:
const { contextBridge } = require('electron'); const lmdb = require('lmdb'); // 先引入lmdb模块 // 用更清晰的名称暴露API contextBridge.exposeInMainWorld('electronAPI', { openLMDB: (options) => lmdb.open(options) });
修改renderer.js:
async function initDB() { try { const blocks = window.electronAPI.openLMDB({ path: "./db/blocks", compression: true, }); console.log('数据库打开成功', blocks); // 后续可执行blocks.put('key', 'value')等操作 } catch (err) { console.error('打开数据库失败', err); } } initDB();
方案B:主进程处理数据库操作(推荐,更安全)
将数据库操作放在主进程,渲染进程通过IPC调用,符合Electron安全规范。
修改preload.js:
const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { openLMDB: (options) => ipcRenderer.invoke('open-lmdb', options), putDB: (key, value) => ipcRenderer.invoke('put-lmdb', key, value), getDB: (key) => ipcRenderer.invoke('get-lmdb', key) });
修改main.js:
const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const lmdb = require('lmdb'); let blocksDB = null; // 保存数据库实例 function createWindow () { const win = new BrowserWindow({ width: 1200, height: 800, autoHideMenuBar: true, icon: path.join(__dirname, 'gigatreelogosvv.ico'), webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, // 保持安全模式 nodeIntegration: false // 关闭nodeIntegration,默认已关闭 } }) win.loadFile('index.html') win.webContents.openDevTools() } // IPC监听:打开数据库 ipcMain.handle('open-lmdb', async (event, options) => { try { blocksDB = lmdb.open(options); return '数据库打开成功'; } catch (err) { console.error(err); throw new Error('打开数据库失败:' + err.message); } }); // IPC监听:写入数据 ipcMain.handle('put-lmdb', async (event, key, value) => { if (!blocksDB) throw new Error('数据库未打开'); try { await blocksDB.put(key, value); return '写入成功'; } catch (err) { throw new Error('写入失败:' + err.message); } }); // IPC监听:读取数据 ipcMain.handle('get-lmdb', async (event, key) => { if (!blocksDB) throw new Error('数据库未打开'); try { return blocksDB.get(key); } catch (err) { throw new Error('读取失败:' + err.message); } }); // 应用生命周期处理 app.whenReady().then(() => { createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); });
修改renderer.js:
async function initDB() { try { const result = await window.electronAPI.openLMDB({ path: "./db/blocks", compression: true, }); console.log(result); // 测试写入 await window.electronAPI.putDB('testKey', 'testValue'); console.log('写入完成'); // 测试读取 const value = await window.electronAPI.getDB('testKey'); console.log('读取到数据:', value); } catch (err) { console.error(err.message); } } initDB();
内容的提问来源于stack exchange,提问作者jean
相关产品推荐
相关产品推荐

