使用Node.js进行多个MySQL查询的方法

时间:2011-07-08 09:51:03

标签: javascript mysql node.js

我是事件/回调样式编程和NodeJS的新手。我正在尝试实现一个使用node-mysql模块提供ddbb数据的小http服务器。

我的问题来自查询结构。由于经常会有查询需要先前查询的结果才能运行,因此我无法同时(异步)运行所有查询,因此我不得不等待一些结果。

我的第一种方法是同时运行所有非依赖查询然后循环,直到所有这些查询都设置了一个标记,表示我已经完成了所以我可以继续使用相关(同步)查询,但是我不知道这是否是正确的方法。

这样的事情:

function x(){
    var result_for_asynch_query_1 = null
    var result_for_asynch_query_2 = null

    mainLoop(){
        // call non-dependant query 1
        // call non-dependant query 2

        // loop until vars are != null

        // continue with queries that require data from the first ones
    }
}

//for each browser request
httpServer{
     call_to_x();
}.listen();

这样我可以在最终结果中节省一些时间,因为我不会以连续方式等待所有响应,而只是等待最长的响应。

有没有一种常见的方法可以做到这一点?我没有遵循的任何设计模式?

4 个答案:

答案 0 :(得分:43)

应该避免厄运的金字塔:

var express = require('express');
var Q = require('Q');
var app = express();

app.get('/',function(req,res){
    var mysql      = require('mysql');

    var connection = mysql.createConnection({
        host     : 'localhost',
        user     : 'root',
        password : ''
    });

    connection.connect();

    function doQuery1(){
        var defered = Q.defer();
        connection.query('SELECT 1 AS solution',defered.makeNodeResolver());
        return defered.promise;
    }

    function doQuery2(){
        var defered = Q.defer();
        connection.query('SELECT 2 AS solution',defered.makeNodeResolver());
        return defered.promise;
    }

    Q.all([doQuery1(),doQuery2()]).then(function(results){
        res.send(JSON.stringify(results[0][0][0].solution+results[1][0][0].solution));
        // Hint : your third query would go here
    });

    connection.end();

});

app.listen(80);
console.log('Listening on port 80');

此示例显示的结果取决于2个独立的计算值。 在doQuery1和doQuery2中查询这些值中的每一个。它们按顺序执行,但是异步执行。

接下来你可以看到Q.all(...基本上在成功时调用“then”回调。在该回调中,计算完成。

使用promises(详细信息:Github Q: promise for Javascriptwikipedia)允许使代码更清晰,单独计算和处理结果并移动事物。

看看添加“doQuery3”作为计算的先决条件是多么容易!

然后将“package.json”吼叫到示例代码:

{
    "name": "hello-world",
    "description": "hello world test app",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "express": "3.2.0",
        "q": "0.9.3",
        "mysql":"2.0.0-alpha7"
    }
}

答案 1 :(得分:13)

另一种解决方案是连接所有语句,以分号结尾。例如,要从多个表中进行选择,您可以使用此查询:

var sql = 'select * from user; select * from admin;'

然后,您只能使用一个连接来执行多个语句:

var connection = mysql.createConnection({multipleStatements: true}) connection.query(sql)

注意:默认情况下禁用多个语句以防止SQL注入。请务必正确转义所有值(see docs)

答案 2 :(得分:11)

尝试以其他方式思考(对异步流howtonode.org

有很好的介绍
var db = get_link_or_pool();

do_queries( callback ) {
    db.query(sql1, function(err, res1) {
        if (err) {
             callback(err);
             return;
        }
        // use res1 ...
        db.query(sql2, function(err, res2) {
             if (err) {
                 callback(err);
                 return;
             }
             callback(null, res2); // think 'return'
        }
    });
}

request_handler(req) {
    do_queries( function(err, result) {
        if(err)
            report_error(err);
        else
            write_result(req, result);
    });
}

答案 3 :(得分:4)

我发现以下内容非常有助于解决这个问题:

取自http://book.mixu.net/node/ch7.html - 这里有很多其他很好的例子!

function async(arg, callback) {
  console.log('do something with \''+arg+'\', return 1 sec later');
  //replace setTimeout with database query  
  setTimeout(function() { callback(arg * 2); }, 1000);
}
// Final task (return data / perform further operations)
function final() { console.log('Done', results); }

// A simple async series:
var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];
function series(item) {
  if(item) {
    async( item, function(result) {
      results.push(result);
      return series(items.shift());
    });
  } else {
    return final();
  }
}
series(items.shift());

“获取一组项目并使用第一项调用系列控制流程函数。系列启动一个async()操作,并将回调传递给它。回调将结果推送到结果数组中,然后调用系列使用items数组中的下一项。当items数组为空时,我们调用final()函数。“ (来自http://book.mixu.net/node/ch7.html