Electron项目MySQL连接池初始化报错:Cannot read property 'find' of null
排查:Uncaught TypeError: Cannot read property 'find' of null
嘿,这个错误的根源其实是LokiJS的自动加载是异步操作,你的代码逻辑顺序踩了异步场景的坑:
当你创建LokiJS实例时开启了autoload: true,数据库的加载和初始化会在后台异步完成,databaseInitialize回调要等加载结束才会执行。但你现在直接在回调函数外面就去获取CurConnection集合——这时候数据库还没加载好呢,CurConnection自然是null,调用find()可不就报错了嘛!
解决办法
我们得把所有依赖LokiJS数据的操作(读配置、创建MySQL连接池)都放到数据库初始化完成之后执行。这里给你两种靠谱的方案:
方案1:用Promise封装,确保异步初始化完成再导出
这是最推荐的方式,能完美适配异步场景,还能处理初始化失败的情况:
var mysql = require('mysql'); var loki = require("lokijs"); var db = new loki('config/config.json', { autoload: true, autoloadCallback: initDatabase, autosave: true, autosaveInterval: 1000 }); // 用Promise来管理连接池的初始化 const poolPromise = new Promise((resolve, reject) => { function initDatabase() { let CurConnection = db.getCollection("CurConnection"); // 如果集合不存在就创建 if (!CurConnection) { CurConnection = db.addCollection("CurConnection"); // 这里可以加个默认配置,避免首次运行没数据报错 // CurConnection.insert({ // $loki: 1, // selservername: "localhost", // selport: 3306, // seldbname: "your_default_db", // selusername: "root", // selpassword: "" // }); } const rows = CurConnection.find({ '$loki': { '$eq': 1 } }); // 先检查有没有找到配置 if (!rows || rows.length === 0) { reject(new Error("找不到MySQL连接配置,请先添加服务器配置")); return; } const row = rows[0]; // 创建MySQL连接池 const connectionPool = mysql.createPool({ multipleStatements: true, host: row.selservername, port: row.selport, user: row.selusername, password: row.selpassword, database: row.seldbname }); resolve(connectionPool); } }); // 导出Promise,外部使用时需要等待初始化完成 module.exports = poolPromise;
外部使用的时候这么写:
const poolPromise = require('./你的文件路径'); poolPromise.then(pool => { // 这里就可以正常用连接池了 pool.query('SELECT * FROM your_table', (err, results) => { if (err) throw err; console.log(results); }); }).catch(err => { console.error('初始化连接池失败:', err); });
方案2:同步加载数据库(仅小数据库适用)
如果你的配置文件特别小,也可以关闭自动加载,手动同步加载数据库,但这种方式会阻塞事件循环,不建议在Electron渲染进程用:
var mysql = require('mysql'); var loki = require("lokijs"); var db = new loki('config/config.json', { autosave: true, autosaveInterval: 1000 }); // 手动同步加载数据库 db.loadDatabase({}, () => { let CurConnection = db.getCollection("CurConnection"); if (!CurConnection) { CurConnection = db.addCollection("CurConnection"); } const rows = CurConnection.find({ '$loki': { '$eq': 1 } }); const row = rows[0]; const connection = mysql.createPool({ multipleStatements: true, host: row.selservername, port: row.selport, user: row.selusername, password: row.selpassword, database: row.seldbname }); module.exports = connection; });
⚠️ 注意:这种方式下,外部模块导入时可能会暂时拿到undefined,得等加载完成后才能用,所以还是方案1更稳妥。
额外提醒
- 首次运行时,
CurConnection集合是新创建的,里面没有数据,rows[0]会是undefined,一定要加个默认配置或者错误判断,不然又会出新的报错。 - 在Electron里,注意
config/config.json的路径问题,最好用app.getPath('userData')来获取官方推荐的用户数据目录,避免权限问题哦。
内容的提问来源于stack exchange,提问作者Ayoob Khan
相关产品推荐
相关产品推荐

