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

NodeJS中如何将SQL查询结果返回到父函数作用域?

解决Brackets扩展中NodeJS查询结果无法传递到父作用域的问题

我正在开发一款Brackets文本编辑器扩展,用来把工作时长存储到数据库并查看时间记录。目前用NodeJS和SQL服务器交互,已经实现了时长录入和SELECT查询,但就是没法把查询结果传递到父函数作用域里传给main.js。我是NodeJS新手,试过回调和Promise但没搞定。现在的情况是,我想让viewTime()函数以Promise形式返回给main.js,要是能把con.connect()改成普通函数,就能通过registerCommand在main.js里调用了。我的代码如下:

(function () { "use strict"; var mysql = require('mysql'); /** * @private * * @return {array} */ function viewTime() { var con = mysql.createConnection({ host: "localhost", user: "root", password: "root", database: "brackets_timer_data" }); con.connect(function(err) { if (err) { console.log(err); } else { console.log("Connected!"); } con.query("SELECT * FROM work_sessions", function (err, result, fields) { if (err) { console.log(err); } //I need to get the result from here }); }); //And return it here so I can pass the variable to main.js } /** * Initializes the test domain with several test commands. * @param {DomainManager} domainManager The DomainManager for the server */ function init(domainManager) { if (!domainManager.hasDomain("view")) { domainManager.registerDomain("view", {major: 0, minor: 1}); } domainManager.registerCommand( "view", // domain name "viewTime", // command name viewTime, // command handler function false, // this command is synchronous in Node "Returns time entry results.", [{}], [{name: "results", // return values type: "array", description: "Time entry results"}] ); } exports.init = init; }());

核心问题分析

你遇到的问题本质是异步操作的结果无法同步返回——con.connect()和con.query()都是异步回调式的,你的viewTime()函数会在数据库操作完成前就执行到末尾,自然返回不了结果。要解决这个,必须把异步操作封装成Promise,同时告诉Brackets的DomainManager这个命令是异步的。

修改后的完整代码

(function () { 
    "use strict"; 
    var mysql = require('mysql'); 

    /** 
     * @private
     * @return {Promise<array>} 返回包含时间记录的Promise
     */ 
    function viewTime() { 
        // 用Promise包装整个异步流程
        return new Promise((resolve, reject) => {
            var con = mysql.createConnection({ 
                host: "localhost", 
                user: "root", 
                password: "root", 
                database: "brackets_timer_data" 
            }); 

            con.connect(function(err) { 
                if (err) { 
                    console.log(err);
                    reject(err); // 连接失败时拒绝Promise,传递错误
                    return;
                } 
                console.log("Connected!"); 

                con.query("SELECT * FROM work_sessions", function (err, result, fields) { 
                    // 无论成功失败,都要关闭数据库连接,避免资源泄漏
                    con.end();
                    
                    if (err) { 
                        console.log(err);
                        reject(err); // 查询失败时拒绝Promise
                        return;
                    } 
                    resolve(result); // 查询成功时,把结果传给Promise的resolve
                }); 
            }); 
        });
    } 

    /** 
     * Initializes the test domain with several test commands. 
     * @param {DomainManager} domainManager The DomainManager for the server 
     */ 
    function init(domainManager) { 
        if (!domainManager.hasDomain("view")) { 
            domainManager.registerDomain("view", {major: 0, minor: 1}); 
        } 
        domainManager.registerCommand( 
            "view", // domain name 
            "viewTime", // command name 
            viewTime, // command handler function 
            true, // 这里改成true!告诉DomainManager这是异步命令(返回Promise)
            "Returns time entry results.", 
            [], // 空参数列表简化写法
            [{name: "results", // return values 
              type: "array", 
              description: "Time entry results"}] 
        ); 
    } 

    exports.init = init; 
}());

关键修改点说明

  1. 用Promise封装异步操作:

    • 把viewTime()改成返回Promise,用resolve(result)传递查询结果,用reject(err)传递错误。这样调用者可以通过.then()或await获取结果。
    • 每次查询完成后调用con.end()关闭连接,防止数据库连接泄漏。
  2. 修改DomainManager注册配置:

    • 把registerCommand的第四个参数(同步/异步标识)从false改成true,因为现在viewTime()返回Promise,属于异步命令,Brackets需要知道这一点才能正确处理返回值。

在main.js中的调用方式

现在你可以在main.js里用异步方式调用这个命令了,比如:

// 假设你已经获取了domain对象
async function loadTimeRecords() {
    try {
        const timeResults = await brackets.app.domains.view.viewTime();
        // 拿到结果后做你需要的处理,比如渲染到UI上
        console.log("时间记录:", timeResults);
    } catch (error) {
        console.error("加载时间记录失败:", error);
    }
}

// 调用函数加载记录
loadTimeRecords();

这样就能顺利把数据库查询结果从Node层传递到Brackets的前端main.js里了!

内容的提问来源于stack exchange,提问作者Isaac Dew

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:39:35