NodeJS mysql同步查询

Posted

技术标签:

【中文标题】NodeJS mysql同步查询【英文标题】:NodeJS mysql sync query 【发布时间】:2017-12-16 19:09:30 【问题描述】:

我想像这样在 nodejs 中运行同步查询...

for (var i in data)

conn.query("Select 1 from user where userid="+data[i].id,function(err,row)
     Rows.push(row);
);



console.log(Rows);

在这段代码中,我的行一直都为空...我想运行同步查询

【问题讨论】:

【参考方案1】:

你可能无法在线程阻塞的意义上同步使用这样的函数(你也不应该!)但如果你使用数据库连接的承诺版本(使用 Bluebird 的 promisifyAll 或特定的在 npm 上可用的 mysql 驱动程序的 promise 版本)和新的 async/await 语法(或基于生成器的协程,用于比 Node 7.x 更早的平台,其中 async/await 不可用 - 另一种选择是使用 Babel 进行转译)。

示例 - 您可以使用这样的代码:

for (var i in data) 
  let row = await conn.query("Select 1 from user where 
  userid="+data[i].id);
  Rows.push(row);

console.log(Rows);

但如果它可以并行运行,那么这样的事情会更高效、更短:

let Rows = await Promise.all(data.map(item =>
  conn.query("Select 1 from user where userid=" + item.id));
console.log(Rows);

有关该主题的更多详细信息,请参阅:

Do async in a blocking program language way? Using async/await + Bluebird to promisifyAll try/catch blocks with async/await Using acyns/await in Node 6 with Babel jQuery: Return data after ajax call success

注意 - 它只能在使用 async 关键字声明的函数内部使用。

警告:您的代码可能容易受到 SQL 注入攻击。您应该在 SQL 中使用占位符而不是字符串连接。我没有修复您代码的这方面 - 有关更多详细信息,请参阅这些答案:

cannot use backtick when using nodejs 7.3.0 Node.js - The multi part could not be bound How to escape mysql special characters with sockets.io/node.js/javascript Node js - Promise Rejection Warning when process a lot of data Is it possible to listen for object instantiation in Node.js?

【讨论】:

【参考方案2】:

您应该使用bluebird npm module 来解决这个问题。使用npm install bluebird安装bluebird

    var Promise = require('bluebird');
    var Rows= [];
    data.forEach(function (obj) 
       conn.query("Select 1 from user where userid="+obj.id,function(err,row)
               Rows.push(row);
       );
      );
       return Promise.all(Rows);
    )

【讨论】:

这行不通。您在 forEach 回调中返回 Promise.all(Rows),该回调在每次迭代时运行一次,并忽略其返回值。此外,您正在一个不包含承诺的数组上运行Promise.all。无论如何,它应该做什么?【参考方案3】:

你也可以使用异步模块。

var async= require('async')
async.eachSeries(arr, function(index, callback)
  conn.query("Select 1 from user where userid="+index, 
    function(err,res) 
      if (err) 
        return console.error('error running query', err);
      else
       Row.push(res);
      
    callback();
);
,function(err)
  if(err)
   return err;
   console.log("all queries executed")
);

【讨论】:

【参考方案4】:

您可以制作一个返回 Promise 的包装器。使用await 可以使其同步:

function promiseWrapper() 
    return new Promise((resolve, reject) => 
        conn.query("SQL_QUERY", queryCallback(resolve, reject);
    


function queryCallback(err, row)
    return (resolve, reject) 
        resolve(row);
    

【讨论】:

以上是关于NodeJS mysql同步查询的主要内容,如果未能解决你的问题,请参考以下文章

node.js 同步 mysql 查询

Elasticsearch-jdbc批量同步mysql数据失败

Mysql和ES数据同步方案汇总

Promise你把握不住?来看看异步转同步改造

Promise你把握不住?来看看异步转同步改造

MySQL第六天(主从同步,数据读写分离)