You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:25:19