简体   繁体   English

使用 NodeJS 从 MySQL 查询

[英]Querying From MySQL Using NodeJS

I am trying to query a MySQL database table.我正在尝试查询 MySQL 数据库表。 I am using NodeJS / Express as my backend.我使用 NodeJS / Express 作为我的后端。

I have set up the MySQL like this.. (Yes I have checked to see if the backend connects to the database. I have just left out the credentials below.)我已经像这样设置了 MySQL ..(是的,我检查了后端是否连接到数据库。我刚刚遗漏了下面的凭据。)

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

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

I'm trying to keep my code organized, so I have this in a configuration file.我试图让我的代码井井有条,所以我在配置文件中有这个。 I want to export the db constant and do db.query() from other files.我想导出 db 常量并从其他文件中执行 db.query() 。

Therefore, I have done this.因此,我做到了这一点。

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

However, when I require db in other files doing the following但是,当我在其他文件中需要 db 时,请执行以下操作

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

It says db.query is not a function.它说 db.query 不是 function。 Anyone know why it would say that?有谁知道为什么会这样说? I can't seem to get it export correctly most likely.我似乎无法正确导出它。

Thanks.谢谢。

In my application I use it this way:在我的应用程序中,我以这种方式使用它:

const mysql = require('mysql');

connection = mysql.createPool({
    host: '***',
    user: '***',
    password: '***',
    database: '***'

});

module.exports = connection;

And where I need to call it:我需要在哪里称呼它:

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

Then just use:然后只需使用:

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

The short answer简短的回答

You probably have a circular dependency, ie you have a file a that require s file b , but file b also require s file a .你可能有一个循环依赖,即你有一个文件a require s 文件b ,但文件brequire s 文件a In combination with using module.exports = something (instead of modifying the existing exports object), this leads to the situation where one of the modules will get an empty object returned from require ing the other one (none of its exports seem to exist there).结合使用module.exports = something (而不是修改现有的exports对象),这会导致其中一个模块将从require另一个模块返回一个空的 object (它的导出似乎不存在那里) )。

The quick fix is most likely to replace module.exports = { app, db } with exports.app = app; exports.db = db快速修复最有可能将module.exports = { app, db }替换为 exports.app = exports.app = app; exports.db = db exports.app = app; exports.db = db or Object.assign(exports, { app, db }) . export.db exports.app = app; exports.db = dbObject.assign(exports, { app, db })

As to why, and what other options exist in case that is not the best solution, read below.至于为什么,以及如果这不是最佳解决方案存在哪些其他选项,请阅读下文。

The long answer长答案

It sounds as if you have a circular dependency problem.听起来好像你有一个循环依赖问题。

Let me explain, and bear with me, we'll eventually get to your problem.让我解释一下,请耐心等待,我们最终会解决您的问题。

See, every module starts out with an empty object as module.exports (also available as exports ).看,每个模块都以一个空的 object 作为module.exports (也可以作为exports使用)。 If you only modify this object by doing exports.something = something (or module.exports.something = something ), things can work in many cases even with a circular dependency at the top level, as long as the properties of the exports object are accessed only later on.如果您仅通过执行 exports.something exports.something = something (或module.exports.something = something修改此 object,那么即使在顶层存在循环依赖关系,只要导出 object 的属性为稍后才访问。 For example:例如:

/* 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

Here we have a circular dependency ( a depends on b , but b also depends on a ).这里我们有一个循环依赖( a依赖于b ,但b也依赖于a )。 Yet, it works.然而,它有效。

The above code works because when a.js is evaluated, its exports object will already exist, and when it then requires b.js and b.js requires a.js again, then even though a.js has not even finished running its top-level code yet, the a variable in b.js can already get assigned the exports object of a.js .上面的代码之所以有效,是因为在评估a.js时,它的exports object 将已经存在,然后当它需要b.js并且b.js再次需要a.js时,即使a.js甚至还没有完成运行它的顶部级代码, b.js中的a变量已经可以分配到 a.js 的exports a.js It is an empty object at that point, but by the time the line return a.getZ() * 3 runs, the object will have the property getZ set.那时它是一个空的 object,但是当行return a.getZ() * 3运行时,object 将设置属性getZ

  1. main requires a main需要a
  2. a requires b a需要b
  3. b requires a and gets an object that is currently empty b需要a并获取当前为空的 object
  4. b defines getY on its exports and returns b在其导出和返回上定义getY
  5. a defines getX and getZ on its exports (which is the exact same object that b already got a reference to!) and returns a在其导出上定义getXgetZ (与b已经得到引用的 object 完全相同!)并返回
  6. main calls a.getX() main调用a.getX()
  7. a.getX calls b.getY a.getX调用b.getY
  8. b.getY only now accesses the property getZ of a which does exist by now (it was set in step 5). b.getY现在只访问现在确实存在的a的属性getZ (它是在步骤 5 中设置的)。

Note that it would not have worked if we had written const { getZ } = require('./a') because then the getZ property would have been accessed already at step 3 when it wouldn't have existed yet.请注意,如果我们编写了const { getZ } = require('./a')则它不会起作用,因为那时getZ属性将在步骤 3 中被访问,而它还不存在。

But, similarly, it also would have stopped working if we had written a.js like this:但是,类似地,如果我们像这样编写a.js ,它也会停止工作:

const b = require('./b')

function getX () {
  return b.getY() * 2
}

function getZ () {
  return 5
}

module.exports = { getX, getZ }

The big difference here is that we are now reassigning the exports object , So, the object that b gets at step 3 is the original (empty) object, but we are then reassigning it to a new object (instead of modifying the existing object), and the code in b never has a chance to get a reference to that object, Then: you have this exact situation: A require gives you an empty object, and trying to call a.getZ will fail with a.getZ is not a function (because it is undefined ). The big difference here is that we are now reassigning the exports object , So, the object that b gets at step 3 is the original (empty) object, but we are then reassigning it to a new object (instead of modifying the existing object) ,并且b中的代码永远没有机会获得对该 object 的引用,然后:您遇到这种情况:A require给您一个空的 object,并且尝试调用a.getZ将失败, a.getZ is not a function (因为它是undefined )。

(By the way, module.exports = something is not the same as exports = something , because the latter reassigns the local exports variable and does not change what other modules will see as exports from yours!) (顺便说一下, module.exports = somethingexports = something不同,因为后者重新分配了本地exports变量,并且不会改变其他模块将看到的导出内容!)

My assumption right now is that you have a similar problem here - that the file that does the DB connection is requiring the file that uses the DB connection, but the other way round as well.我现在的假设是您在这里遇到了类似的问题 - 执行数据库连接的文件需要使用数据库连接的文件,但反过来也是如此。

You now have two options:您现在有两个选择:

  • Replace module.exports = { app, db } with exports.app = app; exports.db = dbmodule.exports = { app, db }替换为 exports.app = exports.app = app; exports.db = db exports.app = app; exports.db = db or Object.assign(exports, { app, db }) - both of which mutate the existing exports object instead of replacing it. export.db exports.app = app; exports.db = dbObject.assign(exports, { app, db }) - 两者都会改变现有的导出 object 而不是替换它。
  • Require one of the files at a later point in time, either by requiring it inside of another function or by creating a placeholder variable let otherModule and exporting an init method that actually fills it using otherModule = require('./otherModule') and then calling this init method in a second step after requiring, thereby decoupling the evaluating of the module code and the requiring of its dependencies, breaking the circular dependency.稍后需要其中一个文件,或者通过在另一个 function 中需要它,或者通过创建一个占位符变量let otherModule并导出一个使用otherModule = require('./otherModule')实际填充它的init方法,然后在 require 之后的第二步调用这个init方法,从而将模块代码的评估和它的依赖项的 require 解耦,打破循环依赖。

The first option is probably the easiest, most immediate solution to the problem.第一个选项可能是解决问题的最简单、最直接的方法。 But, I don't know the rest of your code, so there may be other obstacles that prevent this solution from being viable.但是,我不知道您的代码的 rest,因此可能还有其他障碍阻碍了此解决方案的可行性。

So, let me explain the second option in detail, because it can solve the issue often too.所以,让我详细解释第二个选项,因为它也可以经常解决问题。

Example of the second option:第二个选项的示例:

/* 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

This code now works even though it reassigns module.exports , because now things happen in a different order:即使重新分配module.exports ,此代码现在也可以工作,因为现在事情以不同的顺序发生:

  1. main requires a main需要a
  2. a replaces its exports object with one that contains init , getX and getZ and returns [note that this part of the code previously ran much later] a将其导出 object 替换为包含initgetXgetZ并返回的导出 [请注意,这部分代码之前运行得更晚]
  3. main calls a.init() main调用a.init()
  4. a.init requires b a.init需要b
  5. b requires a and gets its final exports object with all the methods [note that previously it got a not-yet-filled object because a was also not fully loaded yet!] b需要a并使用所有方法获取其最终导出 object [请注意,以前它得到一个尚未填充的 object 因为a还没有完全加载!]
  6. b replaces its exports object with one that contains getY and returns b将其导出 object 替换为包含getY并返回
  7. a.init returns a.init返回
  8. main calls a.getX() main调用a.getX()
  9. Everything works from now on because both a and b by now have references to each others' fully-filled exports objects already从现在开始一切正常,因为ab现在都已经引用了彼此的完全填充的导出对象

The other way to implement the second option of "requiring at a later point in time" is to require the other module inside an exported function that is already used, but this can have its downsides (such as duplicate code if it is needed in many functions, and slightly slower execution because require has to be called over and over again).实现第二个选项“稍后要求”的另一种方法是在已使用的导出 function 中require另一个模块,但这可能有其缺点(例如,如果在许多情况下需要重复代码函数,并且执行速度稍慢,因为require一遍又一遍地调用)。 In our example, it would mean doing this:在我们的示例中,这意味着这样做:

/* b.js */

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

module.exports = { getY }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM