【发布时间】: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 连接和查询处理函数。我相信这可能会解决你的问题。 stackoverflow.com/a/67722081/13772090
-
@MuratColyaran,你的另一个答案对我来说有点过分了,但我想知道我是否尝试使用它的这一部分 const { mySql } = require('./ db.js');在我的 database.js 文件中,我将遇到同样的问题(require 不被理解)。
-
@Nick 不,它不会那样工作。如果您将该答案原样复制到文件中。您可以通过在任何地方调用该函数来运行您想要的任何查询。它工作得非常干净。当然,你必须给环境变量正确。
-
@Nick 双方都需要
db.js。但重要的是您需要为两者使用相同的数据库配置。 (主机、密码 dbname 等)。建立数据库连接后。只需调用该函数并执行查询。我认为会尽力而为的部分。由于此功能不会保持连接处于活动状态,因此您可以根据需要在服务器端和客户端运行查询。
标签: mysql node.js express socket.io