在 node.js 中的客户端和服务器 js 文件之间共享 mysql 连接

Posted

技术标签:

【中文标题】在 node.js 中的客户端和服务器 js 文件之间共享 mysql 连接【英文标题】:Sharing a mysql connection between client and server js files in node.js 【发布时间】:2021-08-16 06:01:57 【问题描述】:

我在这里看到过类似的问题,但没有一个完全像这样,所以我希望我不会重复已经问过的问题。

我对 node.js 和 socket.io 还很陌生,所以请多多包涵,我正在尝试构建一个多聊天室应用程序的项目。

我被困在我试图将我的代码分成“模块”的一步。我的项目目录结构如下。

我的 index.js 启动 express 服务器并设置基本的 socket.io 连接。据我了解,这个起点 index.js 文件是“服务器端”js。

Index.js

const path = require('path')
const http = require('http')
const express = require('express')
const socketio = require('socket.io')
const  generatemsg  = require('./utils/messages')
const  addUser, removeUser, getUser, getUserInRoom  = require('./utils/users')
const pool = require('./utils/dbconfig');
const db = require('../public/js/database');

const app = express()
const server = http.createServer(app)
const io = socketio(server)
const PORT = process.env.PORT || 3000

const publicdir = path.join(__dirname, '../public')

app.use(express.static(publicdir))

io.on("connection", (socket) => 
    console.log("new connection from socket.io")

    socket.on("join", ( username, room , cb) => 

        const  error, user  = addUser( id: socket.id, username, room )

        if (error) 
            return cb(error)
        
        
        socket.join(user.room)

        //generate random color
        const colorsArray = ["red", "green", "lime", "purple", "blue"]
        var arrayPos = Math.floor(Math.random() * colorsArray.length)
        var colorTmp = colorsArray[arrayPos]

        //Add New User to DB
        var userTmp = user.username
        var roomTmp = user.room
        
        db.addCurrentUserToDB(userTmp, roomTmp, colorTmp)

        io.to(user.room).emit("roomData", 
            room: user.room,
            users: getUserInRoom(user.room)
        )
        
        cb()
    )

    socket.on("sendMessage", (msg, cb) => 
        const user = getUser(socket.id)
        io.to(user.room).emit("message", generatemsg(user.username, msg))
        cb()
    )

    socket.on("disconnect", () => 
        const user = removeUser(socket.id)
        console.log(user)
        if (user) 
            io.to(user.room).emit("message", generatemsg(`$user.username left.`))

            io.to(user.room).emit("roomData", 
                room: user.room,
                users: getUserInRoom(user.room)
            )
        
    )
)


server.listen(PORT, () => 
    console.log("server is up at port: " + PORT)
)

所以我对事情何时从 server-side.js 转移到 client-side.js 的理解开始变得对我来说很奇怪。 Index.js 是 server-side.js 因为我可以使用一些变量 = require('some module');

然后在我的 utils 目录中是我的数据库配置文件。为了共享 mysql 连接,我相信我需要创建一个池连接,这就是我在这里尝试做的。

dbconfig.js

const mysql = require('mysql');

const pool  = mysql.createPool(
    connectionLimit : 100,
    host: "xxxx",
    port: 3306,
    user: "xxxx",
    password: "xxxx",
    database: 'xxxx',
    multipleStatements: true
);

pool.getConnection(function(err, connection) 
    if (err) throw err; // not connected!
    
    console.log('Connected from dbconfig.js');
);

module.exports.pool = pool;

由于我不完全理解的原因,utils 文件夹中的文件似乎仍然是服务器端 js,这就是为什么我能够将它们包含到 index.js 文件中并使用database.js 文件(客户端)。

在 public/js 文件夹中,我存储了我将在整个应用程序中随机调用的所有数据库函数。

Database.js(为简洁起见)

    //Add New User
    function addCurrentUserToDB(userTmp, roomTmp, colorTmp) 
    var sql = 'INSERT INTO pzs_info (username, roomname, usercolor) VALUES (?, ?, ?)';

    pool.getConnection(function(err, connection) 
        if (err) throw err; // not connected!
      
        // Use the connection
        connection.query(sql, [userTmp, roomTmp, colorTmp], (err, result, fields) => 
            if (err) throw err;
        
            console.log('Added user' + userTmp); //result.changedRows
            connection.release();
        );
    );

database.js 文件现在似乎是“客户端”js,因此似乎无法访问 mysql 连接(因为它存储在我猜是 server-side.js 文件中),即使我将它导出到 dbconfig.js 文件中。

根据我如何改变上述代码,我会得到错误,从池不是函数或池未定义,在我一直在尝试的最新版本中,如下所示:

Database.js

const dbstuff = require('../../src/utils/dbconfig');

//Add New User
function addCurrentUserToDB(userTmp, roomTmp, colorTmp) 
    var sql = 'INSERT INTO pzs_info (username, roomname, usercolor) VALUES (?, ?, ?)';

    dbstuff.pool.query(sql, [userTmp, roomTmp, colorTmp], function (error, results, fields) 
        if (error) throw error;
        console.log('Added user' + userTmp); //result.changedRows
    );

我猜这是因为此时 database.js 文件现在是 client-side.js 并且不能使用 require 函数。

但有趣的是,即使它让我无法使用来自 console.log 中 database.js 文件的 require 错误消息,它实际上仍然将用户名/房间/颜色写入数据库。去图吧。

我的猜测是节点如何在客户端/服务器端之间共享功能的一些基本逻辑让我完全无法理解。

更新: 好吧,我已经取得了一些进展,这要归功于这里添加 esm 模块的建议,这允许我将 require 与 import 语句混合/匹配。

所以我现在可以从 dbconfig.js 文件中拉入 database.js 文件中的连接(dbconfig 是服务器,数据库是客户端),这很好。

但是我一直在尝试将 database.js 文件放入 chat.js 文件中(它们都是客户端)。

我尝试在 chat.js 文件的顶部添加一个 import 语句

import  updateUserList  from './database.js';

但是这会产生一个语法错误:导入声明可能只出现在模块错误的顶层。

如果我也像这样将 type="module" 添加到我的 chat.html 文件中:

<script src="/js/chat.js" type="module"></script>

然后我得到几个不同的错误。 chat.js 文件出现 404 错误,文件因不允许的 mime 类型错误等而被阻止。

Soo...我又在旋转我的***了。不知道为什么我不能只在我的 chat.html 文件中包含 database.js 文件并收工。

请指教。

【问题讨论】:

提示:可以帮助的一件事是使用 ES6 import 而不是特定于节点的 require 我在回答中给出了一个模块化的 MySQL 连接和查询处理函数。我相信这可能会解决你的问题。 ***.com/a/67722081/13772090 @MuratColyaran,你的另一个答案对我来说有点过分了,但我想知道我是否尝试使用它的这一部分 const mySql = require('./ db.js');在我的 database.js 文件中,我将遇到同样的问题(require 不被理解)。 @Nick 不,它不会那样工作。如果您将该答案原样复制到文件中。您可以通过在任何地方调用该函数来运行您想要的任何查询。它工作得非常干净。当然,你必须给环境变量正确。 @Nick 双方都需要db.js。但重要的是您需要为两者使用相同的数据库配置。 (主机、密码 dbname 等)。建立数据库连接后。只需调用该函数并执行查询。我认为会尽力而为的部分。由于此功能不会保持连接处于活动状态,因此您可以根据需要在服务器端和客户端运行查询。 【参考方案1】:

Database.js 文件中,dbstuff 是您的池变量。使用 dbstuff.query 而不是 dbstuff.pool.query。

【讨论】:

我试过了,我刚得到一个 dbstuff.query is not a function 错误。 =/我认为是因为我不能在客户端js中使用require。【参考方案2】:

@Murat 的 mysql 连接/响应链接绝对有帮助,让我走上了正确的道路。这是另一个问题的链接。

***.com/a/67722081/13772090

但是,最终我最终选择了使用 3rd 方服务的 Pub / Sub 路线,这对我来说比尝试构建自己的基础架构要好得多。如果有人好奇,我会选择 Ably。

谢谢大家!

【讨论】:

以上是关于在 node.js 中的客户端和服务器 js 文件之间共享 mysql 连接的主要内容,如果未能解决你的问题,请参考以下文章

将存储在 S3 存储桶中的文件直接下载到 React 客户端,而不是通过 Node.js 服务器

node.js学习目录

如何递归遍历目录,通过 node.js 中的套接字发送所有文件名?

受祝福的服务器(Node.js)通过 websocket 到浏览器中的 Xterm.js 客户端

关于Node.js的httpClieint请求报错ECONNRESET的原因和解决措施

如何从node js文件中调用一个vanilla JavaScript函数?