nodejs怎么同步查询数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nodejs怎么同步查询数据相关的知识,希望对你有一定的参考价值。

nodejs在IO处理的时候本来就是异步的,这和js引擎的原理是分不开的,如果所有耗时操作都是同步的,那么必然会堵塞当前js主线程,导致并发请求出现排队堵塞的情形。js引擎正是将耗时操作交给libuv内部的线程池来处理,这样js主线程就等着接收libuv的事件轮询回掉就可以了。 参考技术A var sqlite3 = require('sqlite3').verbose();


var async = require('async');


var str = "";

var db = new sqlite3.Database('score.db', function () 
    db.all("select * from score", function (err, res) 
        if (!err) 
           // console.log(JSON.stringify(res));
            str = JSON.stringify(res);
            console.log(str);//@1 这里输出的是有值的str
        else 
            console.log(err);
        
    );
);

console.log(str+"jjjj");//@2 这里输出的Str,是没有值的空的

下面是输出结果:
jjjj 这是@2console打印的,Str是空的

["id":1,"name":"jim","score":"100","id":2,"name":"tom","score":"200"]
这是@1 console打印的,str是有值的。

请问怎样让查询回调先执行,让str获得值,传递出来,然后再执行最后一句@2的打印语句。javascript的异步回调真令人头痛啊,一直不知道怎么解决。

NodeJS mysql同步查询

【中文标题】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怎么同步查询数据的主要内容,如果未能解决你的问题,请参考以下文章

nodejs异步数据库功能需要同步回答

NodeJs中怎么修改 mongoose 查询到的值

nodejs中的异步和同步怎么理解

nodejs:sequelize数据库查询的Op方法

nodejs操作mongodb查询所有数据

续集查询nodejs