首页 > 解决方案 > 已解决 为什么 MySQL 语句在 Node REPL 中逐行键入时可以正常工作,而在函数中却不行?

问题描述

我正在编写一个 reddit 机器人来扫描所有评论并在每次任何用户使用某个关键字写评论时写入 MySQL 表,因此该表会跟踪任何给定用户使用该关键字的次数。所有这一切都很好。当我使用 NodeJS 制作一个允许您查询数据库的小型网站时,问题就来了。当我启动 Node REPL 会话并一次执行以下几行时,一切正常:

const mysql = require('mysql');
data = [];
let db = mysql.createConnection({ // Log into the database
  host: "leHost",
  user: "leUserName",
  password: "leSuperSecurePassword",
  database: "reddit"
});

db.connect(function(err) { // connect to the database via our login
  db.query("SELECT * FROM nicecount", function(err, result, fields) { // Execute this statement
    data.push(result); // add each row that is returned to data[]
  });
});

console.log('returning this data:');
// Data is in the form of [['Username', value], ['Username', value]]
console.log(util.inspect(data));
db.end(); // Close the connection to the database

我得到的东西看起来像这样:

[
RowDataPacket { username: 'benjixinator', value: 3 },
RowDataPacket { username: 'SciNZ', value: 1 },
RowDataPacket { username: 'RetainedByLucifer', value: 1 },
RowDataPacket { username: 'marknielsen777', value: 1 }
]

但是当我把它变成这样的函数时:

const mysql = require('mysql');

function getUserData(username) {
  data = [];
  let db = mysql.createConnection({ // Log into the database
    host: "leHost",
    user: "leUserName",
    password: "leSuperSecurePassword",
    database: "reddit"
  });

  db.connect(function(err) { // connect to the database via our login
    db.query("SELECT * FROM nicecount", function(err, result, fields) { // Execute this statement
      data.push(result); // add each row that is returned to data[]
    });
  });

  console.log('returning this data:');
  // Data is in the form of [['Username', value], ['Username', value]]
  console.log(util.inspect(data));
  db.end(); // Close the connection to the database
  return data;
}

然后运行它,我得到以下信息:

> response = getUserData('benjixinator');
returning this data:
[]
[]
> response
[ undefined ]

我不知道为什么有两个空括号[]。我希望输出是这样的:

> response = getUserData('benjixinator');
returning this data:
[
RowDataPacket { username: 'benjixinator', value: 3 },
RowDataPacket { username: 'SciNZ', value: 1 },
RowDataPacket { username: 'RetainedByLucifer', value: 1 },
RowDataPacket { username: 'marknielsen777', value: 1 }
]
> response
[RowDataPacket { username: 'benjixinator', value: 3 }, RowDataPacket { username: 'SciNZ', value: 1 }, etc...]

我的两部分问题:

  1. 为什么在函数中结果不同?
  2. 如何修改我的代码以使其在作为函数运行时返回 MySQL 数据?

编辑:解决方案

使用@Shadow 提到的这个问题的答案,如何使用 Node 正确地从 mysql 返回结果?,我能够让它为我工作,如下所示:

问题的要点是数据库查询是异步的,这意味着在我访问数组以检查查询结果时,查询结果并未放入数组中。该怎么办?如果只有针对此类问题的特定 JavaScript 功能...

然后,突然之间,JavaScript ES6 Promises出现了!

function getUserData(username ) {
  return new Promise((resolve, reject) => {
    db.query('SELECT * FROM nicecount WHERE username = ?', [username], (err, rows) => { 
      // The addition of the username bit was not part of the solution, it's just part of my project.
      if (rows == undefined) {
        reject(new Error('Error: rows is undefined.'));
      } else {
        resolve(rows);
      }
    });
  });
}

所以现在我有一个函数,getUserData它查询数据库并返回一个承诺。然后,我这样使用这个承诺:

getUserData(req.body.username)
    .then(response => {
      data = [];
      for (let row of response) {
        data.push({
          username: row.username,
          value: row.value
          // ^ I am sure there is a more efficient way to do this,
          // please @ me in a comment with the answer...
        });
      }
      // Now, data[] has the results from the query,
      // and I can do whatever I want with them
      // from here to the end of this .then() block.
    })
    .catch(err => {
      console.log('Error: ' + err);
    });

这就是它的完成方式!再次感谢@Shadow!

标签: javascriptnode.jsmysql-connector

解决方案


推荐阅读