繁体   English   中英

for循环中的node.js mysql查询

[英]node.js mysql query in a for loop

我有两个查询。
首先,

SELECT auctions.name, wowitemdata.itemName, auctions.itemId, 
auctions.buyout, auctions.quantity
FROM auctions
INNER JOIN wowitemdata ON auctions.itemId = wowitemdata.itemID;

返回如下数据:

{
name: 'somename',
itemName: 'someitemname',
itemId: '0000',
buyout: '0001',
quantity: '5',
}

第二个查询使用来自#1的数据来获取比itemId便宜的商品count()。 响应将作为新元素添加到#1->“底切”。

我的功能:

function checkUndercut(data, length){
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt ';
    var From = 'From `auctions` ';
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?';
    var sql = Select + From + Where;
    for(i = 0, len = length; i < len; i++){
        var inserts = [data[i]['itemId'], data[i]['buyout']];
        var ssql = mysql.format(sql, inserts);
        data[i]['undercut'] = i;
        connection.query(ssql, function(err, rows, fields){
            if(!err){
                console.log("check Undercut: " + rows[0].cnt);
                data[i]['undercut'] = rows[0].cnt;
            } else {
                console.log("Error while performing Query");
            };
        });
    };
}

由于查询的异步性质,我无法使用for循环i var追加数据。
我该如何解决?

编辑:我的新问题:
当我搜索名称(searchobj)时,返回的数据落后一步。
假设我搜索“ Tim”,则什么都没有显示。
假设我接下来搜索“ Finn”,那么我在“ Tim”上的数据就会显示出来。

我怀疑这是因为我从checkUndercut函数获取数据的方式。
我创建了一个新的顶级var,appdata,并在使用@simple_programmers建议后,将新代码如下所示:

function(err){
        if(err){
          //handle the error if the query throws an error
        }else{
            appdata = data;
            console.log(appdata);
          //whatever you wanna do after all the iterations are done
        }
    });

console.log发送正确的信息,所以我的问题在于get函数过早发送了响应。

我的get函数:

app.get('/test',function(req, res) {
    console.log("app.get "+searchobj);
    var sqlSELECT = 'SELECT auctions.name, wowitemdata.itemName, auctions.itemId, auctions.buyout, auctions.quantity ';
    var sqlFROM = 'FROM `auctions` ';
    var sqlINNER ='INNER JOIN `wowitemdata` ON auctions.itemId = wowitemdata.itemID ';
    var sqlWHERE = 'WHERE auctions.name LIKE ?';
    var sql = sqlSELECT + sqlFROM + sqlINNER + sqlWHERE;
    var inserts = [searchobj];
    var sql = mysql.format(sql, inserts);
    //console.log("Query: "+sql);
    connection.query(sql, function(err, rows, fields) {
      if (!err){
        var rowLen = rows.length;
        checkUndercut(rows, rowLen);
        console.log(appdata);
        res.send(appdata);
                } else {
    console.log('Error while performing Query.');
    };

    });
}); 

我的问题:

1从异步功能发送数据的正确方法是什么?

2有什么方法可以让我的app.get或res.send等待直到我的数据在发送之前被检索?

编辑2:我可以通过将所有代码放在我的app.get()中来使其工作,但是必须有一个更优雅,更易于阅读的解决方案吗?

我认为,做到这一点的最佳方法是使用一个名为async的节点模块来并行运行事物,并在一切完成后具有一个回调。

async模块中,针对这种情况定义了多种方法,我推荐的方法是forEachOf

假设您的data参数是一个数组,它会像这样-

function checkUndercut(data, length){
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt ';
    var From = 'From `auctions` ';
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?';
    var sql = Select + From + Where;
    async.forEachOf(data, function (dataElement, i, inner_callback){
        var inserts = [dataElement['itemId'], dataElement['buyout']];
        var ssql = mysql.format(sql, inserts);
        dataElement['undercut'] = i;
        connection.query(ssql, function(err, rows, fields){
            if(!err){
                console.log("check Undercut: " + rows[0].cnt);
                dataElement['undercut'] = rows[0].cnt;
                inner_callback(null);
            } else {
                console.log("Error while performing Query");
                inner_callback(err);
            };
        });
    }, function(err){
        if(err){
          //handle the error if the query throws an error
        }else{
          //whatever you wanna do after all the iterations are done
        }
    });
}

因此,基本上的作用是,它遍历data数组并为该数组的每个元素运行查询。 执行查询后,它将调用该迭代本地的回调方法。 一旦完成所有迭代(即,调用了最后一个本地回调),它将调用最终回调,在该回调中,您可以在所有查询执行完毕后做以后想要做的任何事情。

更多关于forEachOf这里- https://caolan.github.io/async/docs.html#eachOf

异步模块-https: //caolan.github.io/async/

如果您只是担心i的作用域以获取特定索引的值,请使用array.forEach

data.forEach(function(datum, i){
  var inserts = [datum['itemId'], datum['buyout']];
  var ssql = mysql.format(sql, inserts);
  datum['undercut'] = i;
  connection.query(ssql, function(err, rows, fields){
    ...
    datum['undercut'] = rows[0].cnt;
    ...
  });
  ...
});

尝试这个

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'pass',
  database: 'db'
});

connection.connect(function(err) 
{
  if (err) throw err;
    connection.query("SELECT * FROM tb", function (err, result, fields) 
    {
      if (err) throw err;
      var test = result;
      var length = Object.keys(result).length;
      console.log(   length   );

      for (var i = 0; i < length; i++) 
      {

      console.log(result[i].column_name);

      };

    });

});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM