【问题标题】:Getting Query object instead of results with Async/await function and npm-mysql使用 Async/await 函数和 npm-mysql 获取查询对象而不是结果
【发布时间】:2020-10-15 17:15:43
【问题描述】:

我有这个函数是async,我正在尝试从npm-mysql db 进行一个简单的查询。

let sortCategory = async (id) => {
    try {
      var sql = 'SELECT * FROM categories WHERE parent_id=?';
      var results = await connection.query(sql, id);
      // console.log(results);
      return(results);
    } catch(err) {
      console.log(err);
      return false;
    }
  }

但不是results 变量中的结果,我只得到查询对象。

Query {                                                                                                                               
  _events:                                                                                                                            
   [Object: null prototype] {                                                                                                         
     error: [Function],                                                                                                               
     packet: [Function],                                                                                                              
     timeout: [Function],                                                                                                             
     end: [Function] },                                                                                                               
  _eventsCount: 4,                                                                                                                    
  _maxListeners: undefined,                                                                                                           
  _callback: undefined,                                                                                                               
  _callSite:                                                                                                                          
   Error                                                                                                                              
       at Protocol._enqueue (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\protocol\Protocol.js:144:48)                      
       at Connection.query (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\Connection.js:198:25)                              
       at sortCategory (C:\Users\fedesc\Sites\borsalino\server\routes\categories.js:35:38)                                            
       at router.post (C:\Users\fedesc\Sites\borsalino\server\routes\categories.js:48:31)                                             
       at process._tickCallback (internal/process/next_tick.js:68:7),                                                                 
  _ended: false,                                                                                                                      
  _timeout: undefined,                                                                                                                
  _timer: Timer { _object: [Circular], _timeout: null },                                                                              
  sql: 'SELECT * FROM categories WHERE parent_id=\'0\'',                                                                              
  values: '0',                                                                                                                        
  .... }

在对象中看到的query

    sql: 'SELECT * FROM categories WHERE parent_id=\'0\'',                                                                              
    values: '0', 

编辑#1

INSERT 查询的异步/等待确实有效。只有当我需要取回数据时,我才得到它。

但我无法恢复结果,即使我确实有一些应该返回的表。 我觉得我对 mysql 和异步调用还有一些不太了解的地方。

谢谢大家。

【问题讨论】:

    标签: javascript mysql express asynchronous async-await


    【解决方案1】:

    正如我在文档中看到的 https://www.npmjs.com/package/mysql

    connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], function (error, results, fields) {
      // error will be an Error if one occurred during the query
      // results will contain the results of the query
      // fields will contain information about the returned results fields (if any)
    });
    

    你的代码应该变成

    
    var sql = 'SELECT * FROM categories WHERE parent_id=?';
    
    connection.query(sql, [id], function (error, results, fields) {
      if(error){
          return error;  
      }
      return results;
    });
    

    【讨论】:

    • 感谢 async/await INSERT 查询确实有效。只有当我需要取回数据时,我才得到它。
    【解决方案2】:

    我像这样使用 mysql 查询的 async/await:

    var getCategories = function (id) {
        return new Promise(function (resolve, reject) {
            var sql = `SELECT * FROM categories WHERE parent_id=?`;
            connection.query(sql, [id], function (err, result) {
                if (!err) {
                    resolve(result);
                } else {
                    resolve({
                        status: "error",
                        message: "Error Getting Data",
                        debug: err
                    });
                }
            });
        });
    };
    
    try {
        var categories = await getCategories();
    } catch (error) {
        console.log(error);
    }
    

    上面的代码和你的很不一样,但是你可以使用上面的方法在其他情况下使用

    【讨论】:

    • 但这只是将async/await 更改为另一个版本的Promise syntax(更脏)。我可以保留我的async 函数,只需更改连接操作以返回回调。但我想在我的代码中维护一个统一的承诺方法。 try/catch 对我来说更具可读性。 async/awaits 也适用于 INSERT 查询。只有当我需要接收数据时,我才得到它。
    • connection.query 没有您在代码中使用的那种语法或函数。 var results = await connection.query(sql, id);
    【解决方案3】:

    首先感谢热心的响应者。

    你们俩的答案确实是一样的,而且是正确的。所以我只接受了最快的响应者。

    NPM Mysql 函数确实以老式回调样式运行(并且需要更新) 对我来说真正奇怪的是 INSERT 语句确实可以开箱即用 - 我猜这是因为如果您不需要检索数据,则实际上不需要回调。

    async/await 是节点的一部分,而不是 mysql。

    所以调用确实触发了,但没有回调。

    Connection.prototype.query = function query(sql, values, cb) {
      var query = Connection.createQuery(sql, values, cb);
      query._connection = this;
    
      if (!(typeof sql === 'object' && 'typeCast' in sql)) {
        query.typeCast = this.config.typeCast;
      }
    
      if (query.sql) {
        query.sql = this.format(query.sql, query.values);
      }
    
      if (query._callback) {
        query._callback = wrapCallbackInDomain(this, query._callback);
      }
    
      this._implyConnect();
    
      return this._protocol._enqueue(query);
    };
    

    因此,您的答案准确无误。

    请允许我详细说明我为我的问题找到的可能解决方案,希望它可能对同样面临这种方法问题的读者有所帮助。

    当我仍在寻找解决方案 here - How to use classes in Node.js (with no pre-compilers), and why you shouldhere - Node.js, MySQL and promises 时,我发现了一种解决方法

    解决方案是"promisifying" mysql 函数和class 类似函数,该函数将所有mysql 函数转换为promise。

    这将提供以async/await 方法使用数据库的选项。

    还有promisify函数使用回调like this one here的工具

    //mysql
    const mysql = require('mysql');
    function Database() {
      this.connection = mysql.createConnection({
        host     : 'localhost',
        user     : '*************',
        password : '*************',
        database : '*************',
        multipleStatements: true
      });
      
      this.query = (sql, args) => {
        return new Promise((resolve, reject) => {
          this.connection.query(sql, args, (err, rows) => {
            if (err)
              return reject(err);
            resolve(rows);
          });
        });
      };
    
      this.close = () => {
        return async () => {
          try {
            this.connection.end(err => {
              if (err) throw err;
              return;
            });
          } catch(e) {
            return e;
          }
        }
      };
    };
    var connection = new Database();
    

    以这种方式设置您的数据库连接将允许您现在像原始问题一样使用async/await

    let sortCategory = async (id) => {
        try {
          var sql = 'SELECT * FROM categories WHERE parent_id=?';
          var results = await connection.query(sql, id);
          // console.log(results);
          return results;
        } catch(err) {
          console.log(err);
          return false;
        }
      }
    

    希望这对任何人都有帮助。

    【讨论】:

      【解决方案4】:

      感谢您提供有用的帖子fedesc。我已经为此苦苦挣扎了好几天。根据您的领导,我最终得到了与我之前的尝试相比优雅的结果:

      'use strict';
      const mysql = require('mysql');
      const config = require('./config.js');
      const util = require('util'); // needed for async support
      
      
      const ac = awaitableConnection( config );
      demoAwait();
      
      async function demoAwait() {
          try {
          const results1 = await ac.query( 'SELECT * FROM table' );
          const results2 = await ac.query( 'SELECT * FROM table WHERE whatever' );
          console.log(results1); // all above results are available
          // throw 'test error'; uncomment to test an error
          } catch ( err ) {
          console.log(err);
          } finally {
          await ac.close();
          }
      }
      
      function awaitableConnection( config ) { // wrapped in a promise
          const connection = mysql.createConnection( config );
          return {
            query( sql, args ) {
              return util.promisify( connection.query )
                .call( connection, sql, args );
            },
            close() {
              return util.promisify( connection.end ).call( connection );
            }
          };
      }

      当查询被放置在一个循环中时,该技术仍然是可读的。我必须感谢 Michał Męciński 的这种技术模式。 2019 年 9 月,他更新了上面链接的文章 fedesc,同时利用了 node.js 8 或更高版本。本文还演示了如何将类似的技术用于事务。 Node.js, MySQL and async/await

      【讨论】:

        猜你喜欢
        • 2020-02-22
        • 1970-01-01
        • 1970-01-01
        • 2021-12-24
        • 2018-12-01
        • 2021-11-20
        • 2018-10-17
        • 2020-09-08
        • 2015-07-22
        相关资源
        最近更新 更多