【问题标题】:Querying From MySQL Using NodeJS使用 NodeJS 从 MySQL 查询
【发布时间】:2020-06-18 18:37:00
【问题描述】:

我正在尝试查询 MySQL 数据库表。我使用 NodeJS / Express 作为我的后端。

我已经像这样设置了 MySQL..(是的,我检查了后端是否连接到数据库。我刚刚遗漏了下面的凭据。)

const db = mysql.createConnection({
  host: '',
  user: '',
  password: '',
  database: ''
});

db.connect((error) => {
  if (error) {
    console.log(error);
  } else {
    console.log("MySQL connected.");
  }
});

我正在努力使我的代码井井有条,因此我将其保存在配置文件中。我想导出 db 常量并从其他文件中执行 db.query()。

因此,我已经这样做了。

module.exports = {
  app: app,
  db: db
};

但是,当我在其他文件中需要 db 时,请执行以下操作

const db = require('../../server');

它说 db.query 不是一个函数。有谁知道为什么会这样说?我似乎无法正确导出它。

谢谢。

【问题讨论】:

    标签: javascript mysql node.js express


    【解决方案1】:

    在我的应用程序中,我这样使用它:

    const mysql = require('mysql');
    
    connection = mysql.createPool({
        host: '***',
        user: '***',
        password: '***',
        database: '***'
    
    });
    
    module.exports = connection;
    

    我需要在哪里称呼它:

    const conn = require('path/to/dbfile.js');
    

    然后只需使用:

    conn.query('SELECT * FROM TEST', function (err, rows) {
        if (err)
            return err;
        return rows;
    });
    

    【讨论】:

      【解决方案2】:

      简短的回答

      你可能有一个循环依赖,即你有一个文件a 那个requires 文件b,但是文件b 也有requires 文件a。结合使用module.exports = something(而不是修改现有的exports 对象),这会导致其中一个模块将获得一个从require 与另一个模块返回的空对象(其导出似乎都没有存在那里)。

      快速修复最有可能将module.exports = { app, db } 替换为exports.app = app; exports.db = dbObject.assign(exports, { app, db })

      至于为什么,以及如果这不是最佳解决方案还有哪些其他选择,请阅读下文。

      长答案

      听起来好像你有一个循环依赖问题。

      让我解释一下,耐心等待,我们最终会解决您的问题。

      请看,每个模块都以 module.exports 的空对象开头(也可作为 exports 使用)。如果您仅通过执行exports.something = something(或module.exports.something = something修改此对象,那么即使在顶层存在循环依赖项,只要导出对象的属性在许多情况下都可以工作稍后才能访问。例如:

      /* a.js */
      const b = require('./b')
      
      exports.getX = function () {
        return b.getY() * 2
      }
      
      exports.getZ = function () {
        return 5
      }
      
      /* b.js */
      const a = require('./a')
      
      exports.getY = function () {
        return a.getZ() * 3
      }
      
      /* main.js */
      const a = require('./a')
      
      console.log(a.getX()) // Returns 30
      

      这里我们有一个循环依赖(a 依赖于b,但b 也依赖于a)。然而,它确实有效。

      上面的代码有效,因为当a.js被评估时,它的exports对象已经存在,然后当它需要b.jsb.js再次需要a.js时,即使a.js还没有即使完成了其顶级代码的运行,b.js 中的a 变量已经可以分配给a.jsexports 对象。那时它是一个空对象,但当return a.getZ() * 3 行运行时,该对象将设置getZ 属性。

      1. main 需要 a
      2. a 需要 b
      3. b 需要 a 并获得一个当前为空的对象
      4. b 在其导出和返回上定义 getY
      5. a 在其导出中定义 getXgetZ(这与 b 已经引用的完全相同的对象!)并返回
      6. main 致电a.getX()
      7. a.getX 致电b.getY
      8. b.getY 现在只能访问 a 的属性 getZ,该属性现在确实存在(在步骤 5 中设置)。

      请注意,如果我们写了const { getZ } = require('./a'),它就不会起作用,因为getZ 属性可能已经在第 3 步被访问了,而它还不存在。

      但是,类似地,如果我们这样写a.js,它也会停止工作:

      const b = require('./b')
      
      function getX () {
        return b.getY() * 2
      }
      
      function getZ () {
        return 5
      }
      
      module.exports = { getX, getZ }
      

      这里最大的不同是我们现在正在重新分配导出对象!所以,b 在第 3 步得到的对象是原始(空)对象,但我们随后将其重新分配给一个新对象(而不是修改现有对象),b 中的代码永远没有机会获取对该对象的引用!然后,您会遇到这种情况:require 给您一个空对象,尝试调用 a.getZ 将失败并返回 a.getZ is not a function(因为它是 undefined)。

      (顺便说一下,module.exports = something exports = something 相同,因为后者重新分配了本地exports 变量,并且不会更改其他模块将看到的从您的导出中看到的内容!)

      我现在的假设是您在这里遇到了类似的问题 - 进行 DB 连接的文件需要 使用 DB 连接的文件,但反过来也是如此。

      您现在有两个选择:

      • module.exports = { app, db } 替换为exports.app = app; exports.db = dbObject.assign(exports, { app, db }) - 两者都会改变现有 导出对象而不是替换它。
      • 稍后需要其中一个文件,方法是在另一个函数中需要它,或者通过创建一个占位符变量let otherModule 并导出一个init 方法,该方法实际上使用otherModule = require('./otherModule') 填充它,然后调用这个init方法在require之后的第二步,从而解耦了模块代码的求值和依赖的require,打破了循环依赖。

      第一个选项可能是解决问题的最简单、最直接的方法。但是,我不知道您的其余代码,因此可能存在其他障碍阻止此解决方案可行。

      所以,让我详细解释第二个选项,因为它也可以经常解决问题。

      第二个选项的例子:

      /* a.js */
      let b
      
      function getX () {
        return b.getY() * 2
      }
      
      function getZ () {
        return 5
      }
      
      function init () {
        b = require('./b')
      }
      
      module.exports = { init, getX, getZ }
      
      /* b.js */
      const a = require('./a')
      
      function getY = function () {
        return a.getZ() * 3
      }
      
      module.exports = { getY }
      
      /* main.js */
      const a = require('./a')
      a.init()
      
      console.log(a.getX()) // Returns 30
      

      这段代码现在可以工作了即使它重新分配了module.exports,因为现在事情以不同的顺序发生了:

      1. main 需要 a
      2. a 将其导出对象替换为包含 initgetXgetZ 的对象并返回 [请注意,这部分代码之前运行得更晚]
      3. main 致电 a.init()
      4. a.init 需要 b
      5. b 需要 a 并使用所有方法获取其最终导出对象 [请注意,之前它得到了一个尚未填充的对象,因为 a 还没有完全加载!]
      6. b 将其导出对象替换为包含 getY 的对象并返回
      7. a.init返回
      8. main 致电a.getX()
      9. 从现在开始一切正常,因为 ab 现在已经引用了彼此的完全填充的导出对象

      实现“稍后要求”的第二个选项的另一种方法是require 已使用的导出函数中的另一个模块,但这可能有其缺点(例如重复代码,如果许多函数都需要它,并且执行速度稍慢,因为必须一遍又一遍地调用require)。在我们的示例中,这意味着这样做:

      /* b.js */
      
      function getY () {
        const a = require('./a')
        return a.getZ() * 3
      }
      
      module.exports = { getY }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 2015-05-12
        • 2018-09-30
        • 2023-03-28
        • 2019-03-09
        • 2020-11-03
        • 1970-01-01
        相关资源
        最近更新 更多