【问题标题】:Node MySql Callback for Multiple Queries多个查询的节点 MySql 回调
【发布时间】:2015-07-21 04:33:01
【问题描述】:

我在尝试创建将行添加到我在 MySql 数据库上创建的新表的逻辑时遇到了一个问题。添加行时,我需要查询数据库 4 次以检查其他行,然后将正确的值添加到新行。我正在使用 node.js 和 mysql 模块来完成此操作。在编码时我遇到了一个障碍,在插入新行之前,代码不会等待 4 个查询完成,这会为每次找到的值提供 0 值。经过一番研究,我意识到回调函数是有序的,看起来像这样:

var n = 0;
connection.query("select...", function(err, rows){
    if(err) throw err;
    else{
        if(rows.length === 1) ++n;
    }
    callback();
});

function callback(){
    connection.query("insert...", function(err){
         if(err) throw err;
    });
}

注意:选择查询只能返回一项,因此 if 条件不应影响此问题。

只有一个查询要等待的回调函数对我来说很清楚,但是对于多个要等待的查询,我有点迷失了。我唯一的想法是创建另一个变量,该变量在调用回调之前递增,然后在回调函数的参数中传递。然后在回调内部,查询可以由 if 语句封装,条件是 this 是等于需要调用的查询数的变量,这里我的目的是 4。我可以看到这个工作,但不确定这种情况是否已经有内置解决方案,或者是否已经开发了其他更好的解决方案。

【问题讨论】:

    标签: javascript mysql node.js callback


    【解决方案1】:

    您需要async (https://github.com/caolan/async)。你可以用这个模块做一个非常复杂的逻辑。

    var data = {} //You can do this in many ways but one way is defining a global object so you can add things to this object and every function can see it
    
    firstQueryFunction(callback){
        //do your stuff with mysql
        data.stuff = rows[0].stuff; //you can store stuff inside your data object
        callback(null); 
    }
    
    secondQueryFunction(callback){
        //do your stuff with mysql
        callback(null);
    }
    
    thirdQueryFunction(callback){
        //do your stuff with mysql
        callback(null);
    }
    
    fourthQueryFunction(callback){
        //do your stuff with mysql
        callback(null);
    }
    
    //This functions will be executed at the same time
    async.parallel([
        firstQueryFunction,
        secondQueryFunction,
        thirdQueryFunction,
        fourthQueryFunction
    ], function (err, result) {
         //This code will be executed after all previous queries are done (the order doesn't matter).
         //For example you can do another query that depends of the result of all the previous queries.
    });
    

    【讨论】:

    • 我了解这将如何解决我的问题,即在其他查询之前执行查询,但这不会比我描述的方法总体上慢吗?如果我错了,请纠正我,但是查询的异步调用和检查是否需要调用是否比同步调用查询更快?我可能不清楚,但 4 个选择查询不需要对它们有任何顺序
    • 我明白,当时我没有收到问题,但有了这些信息,我正在编辑我的答案;)
    • @yanman1234 你去吧,我刚刚编辑了我的答案,以便同时运行 4 个查询并等待它们都运行最后一个函数。
    • 感谢您的帮助。异步看起来确实可以帮助我解决这个问题,我将开始研究它。
    【解决方案2】:

    根据 Gesper 的回答,我建议使用异步库,但是,我可能会建议并行运行(除非第一个查询的结果用作第二个查询的输入)。

    var async = require('async');
    
    function runQueries(param1, param2, callback) {
    
        async.parallel([query1, query2, query3(param1, param2), query4],
            function(err, results) {
                if(err) {
                    callback(err);
                    return;
                }
    
                var combinedResult = {};
                for(var i = 0; i < results.length; i++) {
                    combinedResult.query1 = combinedResult.query1 || result[i].query1;
                    combinedResult.query2 = combinedResult.query2 || result[i].query2;
                    combinedResult.query3 = combinedResult.query3 || result[i].query3;
                    combinedResult.query4 = combinedResult.query4 || result[i].query4;
                }
                callback(null, combinedResult);
            });
    }
    
    
    function query1(callback) {
        dataResource.Query(function(err, result) {
            var interimResult = {};
            interimResult.query1 = result;
            callback(null, interimResult);
        });
    }
    
    function query2(callback) {
        dataResource.Query(function(err, result) {
            var interimResult = {};
            interimResult.query2 = result;
            callback(null, interimResult);
        });
    }
    
    function query3(param1, param2) {
        return function(callback) {
            dataResource.Query(param1, param2, function(err, result) {
                var interimResult = {};
                interimResult.query3 = result;
                callback(null, interimResult);
            });
        }
    }
    
    function query4(callback) {
        dataResource.Query(function(err, result) {
            var interimResult = {};
            interimResult.query4 = result;
            callback(null, interimResult);
        });
    }
    

    Query3 显示使用“传递”到查询函数的参数。

    我相信有人可以向我展示一种更好的组合结果的方法,但这是迄今为止我想出的最好的方法。使用临时对象的原因是,传递给回调的“results”参数是一个结果数组,很难确定哪个结果对应哪个查询。

    祝你好运。

    【讨论】:

    • 我喜欢你的回答,但我不太确定你是否可以传递这样的参数。我个人使用过async.apply(query3,param1,param2)
    • 我不知道 async.apply,看起来这是传递额外参数的正确方法,而我的方法是 hack。
    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多