【问题标题】:node.js async/await using with MySQLnode.js async/await 与 MySQL 一起使用
【发布时间】:2017-10-15 17:02:20
【问题描述】:

我需要同步所有结果并附加到带有 async/await 关键字(如 c#)的字符串。

我是 node.js 的新手,我无法将这种新语法适应我的代码。

var string1 = '';
var string2 = '';
var string3 = '';
var string4 = '';

DatabasePool.getConnection(function(err, connection) {

        connection.query(query,function (err, result) {
            if (err){};
            string1 = result;
        });

        connection.query(query,function (err, result) {
            if (err){};
            string2 = result;
        });     

        connection.query(query,function (err, result) {
            if (err){};
            string3 = result;   
        });

        connection.query(query,function (err, result) {
            if (err){};
            string4 = result;
        }); 

       //I need to append all these strings to appended_text but  
       //all variables remain blank because below code runs first.
       var appended_text = string1 + string2 + string3 + string4;
});

【问题讨论】:

  • 刚刚检查,您使用的是支持异步/等待的节点版本,对吗?
  • 是的最新版本。

标签: javascript mysql node.js asynchronous


【解决方案1】:

假设你使用的 ORM 是基于 Promise 的,你可以做这样的事情

async function buildString() {
  try {
    const connection = await DatabasePool.getConnection();
    const string1 = await connection.query(query);
    const string2 = await connection.query(query);
    const string3 = await connection.query(query);
    const string4 = await connection.query(query);

    return string1 + string2 + string3 + string4;
  } catch (err) {
    // do something
  }
}

通过将await 放在调用前面,任何promise 都可以与async/await 一起使用。但是,请注意 this 函数必须在 async 函数“包装器”中使用。您需要处理try/catch 块中的错误。

我还想指出,这 4 个查询不是同时运行的。你仍然需要为此使用 Promise.all。

【讨论】:

  • 注意 await 只能在异步方法中使用。
  • 谢谢@WilcoBakker。我实际上只是在编辑我的答案:)
  • 我使用mysql包。我认为这不是基于promise的?我应该使用哪个mysql包?
  • 有很多,所以我认为您可能需要一些时间来探索权衡。你可能会遇到的一些是:objection.js、bookshelf、sequelize
  • 如何从查询中获取返回的行值而不是获取字符串?
【解决方案2】:

您必须确保您使用的 mysql 库支持 async/await 所需的 Promises,或者使用像 Bluebird's promisifyAll 这样的工具来包装库。

async function appendedText() {
  const connection = await DatabasePool.getConnectionAsync();
  const [string1, string2, string3, string4] = await [
    connection.query(query1),
    connection.query(query2),
    connection.query(query3),
    connection.query(query4),
  ];
  return string1 + string2 + string3 + string4;
}

请注意,调用 appendedText() 实际上会返回一个 Promise 而不是一个值。

appendedText().then(appended_text => {});

【讨论】:

  • 你真的可以像这样使用 await 来模仿 Promise.all 吗?任何想法我可以在哪里找到更多信息,因为我的快速谷歌搜索返回了非常复杂的方法。
  • @adam-beck,它工作了一段时间......不过现在它需要一个Promise.all()。见这里:stackoverflow.com/questions/34382710/…
【解决方案3】:

使用mysql2数据包。它具有承诺包装器,因此您可以这样做:

async function example1 () {
  const mysql = require('mysql2/promise');
  const conn = await mysql.createConnection({ database: test });
  let [rows, fields] = await conn.execute('select ?+? as sum', [2, 2]);
}

【讨论】:

  • 这是最好的答案......圣牛 Mysql2 比 mysql快得多,并且提供了大量 mysql 没有的东西,比如 promises、压缩和准备好的语句。
  • 使用 await conn.end() 执行查询后不要忘记结束连接;或者更好地使用池而不是像 createPool 和 end pool 这样的连接。
  • 这应该是公认的答案,因为 mysql 现在已弃用,mysql2 至今仍在维护并支持异步
  • 我有点困惑,我需要为每个查询创建与 MySQL 的连接还是将 conn 设为全局并在所有路由中使用?
  • https://npmcompare.com/compare/mysql,mysql2 --> mysql2 是一个更好的包,而且它有更多意义的完整错误消息,这个比较不会告诉
【解决方案4】:

您似乎使用了mysqljs,它不是基于承诺的库。所以你不能使用这个库来实现你想要的。所以你可以做的是使用一个基于承诺的库,比如Sequelize,或者按照评论的建议:

使用 Bluebird 的 promisifyAll 之类的工具来包装库。

我对包装的东西不太了解,所以我所做的就是切换到续集。

【讨论】:

    【解决方案5】:

    如果您恰好在 Node 8+ 中,则可以将原生 util.promisify() 与节点 mysql 结合使用。

    不要忘记用bind() 调用它,这样this 就不会搞砸了:

    const mysql = require('mysql'); // or use import if you use TS
    const util = require('util');
    const conn = mysql.createConnection({yourHOST/USER/PW/DB});
    
    // node native promisify
    const query = util.promisify(conn.query).bind(conn);
    
    (async () => {
      try {
        const rows = await query('select count(*) as count from file_managed');
        console.log(rows);
      } finally {
        conn.end();
      }
    })()
    

    【讨论】:

    • 感谢关于添加绑定的说明。我花了太长时间试图弄清楚为什么我在使用 Promisify 时遇到问题。
    • 非常感谢有关正确绑定方法的提示
    • 如果我必须为查询函数提供 2 个参数,打字稿会给出错误“预期 1 个参数”。我使用了两个参数,因为查询字符串包含?。有没有办法避免在单个查询字符串中附加第二个参数?
    • 对于打字稿:const 查询:(arg1: string, arg2?: string[])=>Promise = promisify(db.query).bind(db);
    • mysql-async-simple 包为您完成了这项工作。
    【解决方案6】:

    如果您想使用 mysql(也称为 mysqljs),如果您不想使用包装器,则必须做一些工作。但这很容易。下面是连接函数的样子:

    const mysql = require('mysql')
    
    var my_connection = mysql.createConnection({ ... })
    
    async function connect()
    {
        try
        {
            await new Promise((resolve, reject) => {
                my_connection.connect(err => {
                    return err ? reject(err) : resolve()
                })
            })
        }
        catch(err)
        {
            ...handle errors...
        }
    }
    
    connect()
    

    如您所见,await 将知道如何处理一个 Promise。您创建此类并在回调实现中使用解析/拒绝函数。这就是它的全部内容,真的,所以使用包装器可能有点多,除非你经常访问你的数据库。

    【讨论】:

      【解决方案7】:

      或者使用mysql-async-simple

      https://www.npmjs.com/package/mysql-async-simple

      const { makeDb } = require('mysql-async-simple');
      const mysql = require("mysql");
       
      const connection = mysql.createConnection({
          host: process.env.HOST,
          user: process.env.USER,
          password: process.env.PASSWORD,
          database: process.env.DB
      });
      const db = makeDb();
      await db.connect(connection);
       
      try {
          const users = await db.query(connection, 'SELECT * FROM users');
      } catch (e) {
          // handle exception
      } finally {
          await db.close(connection);
      }

      【讨论】:

        【解决方案8】:

        您可以像这样使用promise-mysql 包:

        const mysql = require('promise-mysql')
        
        const getDbConnection = async () => {
          return await mysql.createConnection({
            host: process.env.HOST,
            user: process.env.USER,
            password: process.env.PASSWORD,
            database: process.env.DB
          })
        }
        
        const getUsers = async () => {
          const db = await getDbConnection()
          const users = await db.query("SELECT * FROM users")
          await db.end()
          return users
        }
        
        

        【讨论】:

          【解决方案9】:

          正如LeOn - Han Li 所说,我包含了一些小的修改,因为我必须处理结果。

          var mysql = require('mysql');
          const util = require('util');
          
          const conn = mysql.createConnection({
            host     : '127.0.0.1',
            user     : 'user',
            password : 'password',
            database : 'database'
          });
          
          const query = util.promisify(conn.query).bind(conn);
          
          let result = async function() {
              var userCourse = [];
              try {
                  const rows = await query('select * as count from file_managed');
              } finally {
                  conn.end();
                  return userCourse;
              }
          };
          
          result()
          .then(value => {
              console.log(value)
          });
          

          【讨论】:

            【解决方案10】:

            我们可以在 mysql.connect

            中实现 promise,而不是使用 utilpromise/mysql

            var con = require('mysql');

            var mysql = con.createConnection({
                host: "localhost",
                user: "root",
                password: "pass",
                database: "test"
            });
            
            async function asyncAwait(req, res) {
                var promise1;
                mysql.connect((err) => {
                    promise1 = new Promise((resolve, reject) => {
                        console.log('Mysql: Connected');
                        resolve(response.write(uc.upperCase('Connected\n')));
                    });
                    promise1
                        .then(() => {
                         //Implement the logic here
                        })
                        .catch(error => {
                            console.log(error)
                        });
                })
            }
            await asyncAwait();
            

            【讨论】:

              猜你喜欢
              • 2019-01-29
              • 2018-07-15
              • 1970-01-01
              • 2017-11-05
              • 2019-04-15
              • 2014-06-19
              • 2018-01-14
              • 2018-09-12
              • 1970-01-01
              相关资源
              最近更新 更多