NodeJS 如何正确地返回一个结果从mysql与节点?

iyfamqjs  于 2023-01-30  发布在  Node.js
关注(0)|答案(6)|浏览(144)

在代码中

var stuff_i_want = '';
stuff_i_want = get_info(parm);

函数get_info:

get_info(data){
      var sql = "SELECT a from b where info = data"
      connection.query(sql, function(err, results){
            if (err){ 
              throw err;
            }
            console.log(results[0].objid); // good
            stuff_i_want = results[0].objid;  // Scope is larger than function
            console.log(stuff_i_want); // Yep. Value assigned..
    }

在更大的范围内

stuff_i_want = null

关于返回mysql数据并将其赋给变量,我遗漏了什么?
=============根据Alex建议的新代码

var parent_id = '';
    get_info(data, cb){
          var sql = "SELECT a from b where info = data"
          connection.query(sql, function(err, results){
                if (err){ 
                  throw err;
                }
                return cb(results[0].objid);  // Scope is larger than function
    }

====正在使用新代码

get_data(parent_recording, function(result){ 
    parent_id = result;
    console.log("Parent ID: " + parent_id); // Data is delivered
  });

不过

console.log("Parent ID: " + parent_id);

在函数范围之外parent_id为null

qyswt5oh

qyswt5oh1#

你需要用javascript来处理异步调用和回调,这不是C#,PHP等...
下面是使用您的代码的示例:

function get_info(data, callback){
      
      var sql = "SELECT a from b where info = data";

      connection.query(sql, function(err, results){
            if (err){ 
              throw err;
            }
            console.log(results[0].objid); // good
            stuff_i_want = results[0].objid;  // Scope is larger than function

            return callback(results[0].objid);
    })
}

//usage

var stuff_i_want = '';

 get_info(parm, function(result){
    stuff_i_want = result;

    //rest of your code goes in here
 });

当调用get_info时,它又调用connection.query,后者接受回调(这就是function(err, results)
然后将作用域传递给此回调,依此类推。
欢迎来到javascript回调地狱...
当你掌握了窍门,这很容易,只是需要一点时间来适应,来自像C#这样的东西

qxgroojn

qxgroojn2#

我猜你真正想做的是返回一个带有结果的Promise对象,这样你就可以处理从DBMS检索数据的异步操作:当你得到结果时,你利用Promiseresolve函数以某种方式"返回值"/"解析承诺"。
下面是一个例子:

getEmployeeNames = function(){
  return new Promise(function(resolve, reject){
    connection.query(
        "SELECT Name, Surname FROM Employee", 
        function(err, rows){                                                
            if(rows === undefined){
                reject(new Error("Error rows is undefined"));
            }else{
                resolve(rows);
            }
        }
    )}
)}

在调用者端,使用then函数管理实现,使用catch函数管理拒绝。
下面是一个使用上面代码的示例:

getEmployeeNames()
.then(function(results){
  render(results)
})
.catch(function(err){
  console.log("Promise rejection error: "+err);
})

此时,您可以为结果设置视图(结果实际上以对象数组的形式返回):

render = function(results){ for (var i in results) console.log(results[i].Name) }
    • Edit**我将添加一个基本示例,说明如何返回带有结果的HTML内容,这是Node更典型的场景,只需使用promise的then函数设置HTTP响应,然后在http://localhost:3001打开浏览器
require('http').createServer( function(req, res){
if(req.method == 'GET'){
    if(req.url == '/'){
        res.setHeader('Content-type', 'text/html');
        getEmployeeNames()
        .then(function(results){
          html = "<h2>"+results.length+" employees found</h2>"
          html += "<ul>"
          for (var i in results) html += "<li>" + results[i].Name + " " +results[i].Surname + "</li>";
          html += "</ul>"
          res.end(html);
        })
        .catch(function(err){
          console.log("Promise rejection error: "+err);
          res.end("<h1>ERROR</h1>")
        })
    }
}
}).listen(3001)
slhcrj9b

slhcrj9b3#

五年后,我对异步操作有了更好的理解,并且使用ES6中新的async/await语法重构了这段代码:

const mysql = require('mysql2') // built-in promise functionality
const DB = process.env.DATABASE
const conn = mysql.createConnection(DB)

async function getInfo(data){
  var sql = "SELECT a from b where info = data"
  const results = await conn.promise().query(sql)
  return results[0]
}

module.exports = {
  getInfo
}

然后,无论何时需要这些数据,我都会将其 Package 在一个异步函数中,调用getInfo(data)并根据需要使用结果。

g52tjvyc

g52tjvyc4#

在这种情况下,我将新记录插入到子表中,并且需要prent记录键(仅基于名称)。
这是理解节点异步本质的一个很好的例子。
我需要将影响子记录的所有代码 Package 在调用中,以找到父记录ID。
我是从顺序(PHP、JAVA)的Angular 来处理这个问题的,这是完全错误的。

wvmv3b1j

wvmv3b1j5#

如果你发送一个承诺来解决问题会更容易,例如

function get_info(data, promise){

      var sql = "SELECT a from b where info = data";

      connection.query(sql, function(err, results){
            if (err){ 
              throw err;
            }
            console.log(results[0].objid); // good
            stuff_i_want = results[0].objid;  // Scope is larger than function
            promise.resolve(results[0].objid);
    }
}

这样,Node.js将保持快速,因为在您的承诺等待解决时,它忙碌其他事情

h22fl7wq

h22fl7wq6#

我已经为这个目标努力了几个星期,但没有任何结果,我终于找到了一种方法,可以使用await/async和promises将任何mysql查询的结果赋给一个变量。
你不用懂承诺才能用,呃,反正我也不会用承诺
我使用数据库的Model类来实现它,如下所示:

class DB {
    constructor(db) {
        this.db = db;
    }

    async getUsers() {
        let query = "SELECT * FROM asimov_users";
          return this.doQuery(query)
    }

    async getUserById(array) {
      let query = "SELECT * FROM asimov_users WHERE id = ?";
      return this.doQueryParams(query, array);
    }

    // CORE FUNCTIONS DON'T TOUCH
    async doQuery(queryToDo) {
        let pro = new Promise((resolve,reject) => {
            let query = queryToDo;
            this.db.query(query, function (err, result) {
                if (err) throw err; // GESTION D'ERREURS
                resolve(result);
            });
        })
        return pro.then((val) => {
            return val;
        })
    }
    async doQueryParams(queryToDo, array) {
      let pro = new Promise((resolve,reject) => {
        let query = queryToDo;
        this.db.query(query, array, function (err, result) {
            if (err) throw err; // GESTION D'ERREURS
            resolve(result);
        });
      })
      return pro.then((val) => {
        return val;
      })
    }
}

然后,你需要示例化你的类,方法是把参数传递给构造函数,即mysql给出的connection变量,然后,你所要做的就是用await调用你的类方法之一,这样,你就可以链接查询,而不用担心作用域。
示例:

connection.connect(function(err) {
    if (err) throw err;
    let DBModel = new DB(connection);

    (async function() {
        let oneUser = await DBModel.getUserById([1]);
        let allUsers = await DBModel.getUsers();

        res.render("index.ejs", {oneUser : oneUser, allUsers : allUsers});
    })();

});

注:

  • 如果需要执行另一个查询,只需在类中编写一个新方法,并在代码中使用async function中的await调用它,只需复制/粘贴方法并修改它
  • 类中有两个"核心函数",doQuerydoQueryParams,第一个只接受一个字符串作为参数,基本上是你的mysql查询。第二个用于你的查询中的参数,它接受一个数组值。
  • 需要注意的是,你的方法的返回值总是一个对象数组,这意味着如果你只返回一行,你必须执行var[0],如果是多行的话,就在上面循环。

相关问题