node.js - 如何正确取出 NodeJs 中 expressWs 模块的逻辑?
问题描述
你好 stackoverflow 社区。这是我在这个网站上的第一个问题。我花了两周时间努力研究如何将 expressWs 逻辑(前端的聊天窗口)取出到模块中,然后在我的 NodeJS 服务器文件中导入模块。目前,使用此代码,我收到错误“WebSocket 已处于 CLOSING 或 CLOSED 状态。” 如果我在不返回 ws 的情况下编写导出,错误消失,但 websocket 仍然不起作用
我当前的代码
expressWs.js // 我的主服务器文件
require('dotenv').config()
const sequelize = require("./db")
const fileUpload = require("express-fileupload")
const cors = require("cors")
const router = require("./routes/index")
const errorHandler = require("./middleware/ErrorHandlingMiddleware")
const path = require("path")
const fs = require('fs')
const websocketController = require('./websocket/websocketController')
const expressWsModule = require('./websocket/expressWsModule')
var express = require('express');
var expressWs = require('express-ws');
const { send } = require('process')
var expressWs = expressWs(express());
var app = expressWs.app;
app.use(express.static('public'));
var aWss = expressWs.getWss('/');
const PORT = process.env.PORT
app.use(cors({
origin: '*'
}))
app.use(express.json())
app.use(fileUpload({}))
app.use(express.static(path.resolve(__dirname, "static")))
app.use('/api',router)
app.use(errorHandler)
let history = []
let clients = []
let currentClient
app.ws('',websocketController(app))
const start = async () => {
try {
await sequelize.authenticate()
await sequelize.sync()
// app.listen(PORT,() => console.log(`Server started on port ${PORT}`) )
// server.listen(PORT)
app.listen(PORT);
} catch (e){
console.log(e)
}
}
start()
websocketController.js // expressWs的逻辑
module.exports = function websocketController(app){
return function (ws){
console.log('ws module')
let history = []
let clients = []
let currentClient
app.ws('/echo', (ws, req) =>{
var aWss = app.getWss('/echo')
console.log('Socket Connected');
ws.send(JSON.stringify(history))
console.log('history',history)
ws.on('message', msg => {
msg = JSON.parse(msg)
currentClient = msg.username.slice()
if(msg.event === 'message'){
history.push(msg)
history.slice(-100)
}
if(msg.event === 'connection'){
clients.push(currentClient)
}
console.log('clients',clients)
aWss.clients.forEach(client => {
// client.send(msg)
client.send(JSON.stringify(msg))
console.log('msg',msg)
})
})
ws.on('close', () => {
console.log('WebSocket was closed')
console.log('currentClient',currentClient)
console.log('clients after filter',clients)
clients.splice(clients.indexOf(currentClient),1)
currentClient = undefined
})
})
}
}
解决方案
在查看了一些示例后,我终于编写了工作模块。据我所知,let aWss = expressWs.getWss('/echo')
您将无法通过服务器包装应用程序并将 expressWs 包装在同一模块中,然后导出应用程序和服务器。这是我的工作 expressWs 模块代码
require('dotenv').config()
const path = require("path")
const fs = require('fs')
var express = require('express');
const app = express()
var server = require('http').Server(app);
var expressWs = require('express-ws')(app,server);
let history = []
let clients = []
let currentClient
let aWss = expressWs.getWss('/echo');
// console.log('in main',{aWss})
app.ws('/echo', (ws, req) =>{
console.log('Socket Connected');
// ws.send(history)
ws.send(JSON.stringify(history))
// currentClient = aWss.clients
// clients.push(currentClient)
console.log('history',history)
// function broadcastMessage(message) {
// aWss.clients.forEach(client => {
// client.send(JSON.stringify(message))
// })
// }
ws.on('message', msg => {
// ws.send(msg)
msg = JSON.parse(msg)
currentClient = msg.username.slice()
if(msg.event === 'message'){
history.push(msg)
history.slice(-100)
}
if(msg.event === 'connection'){
clients.push(currentClient)
}
console.log('clients',clients)
aWss.clients.forEach(client => {
// client.send(msg)
client.send(JSON.stringify(msg))
console.log('msg',msg)
})
})
ws.on('close', () => {
console.log('WebSocket was closed')
console.log('currentClient',currentClient)
console.log('clients after filter',clients)
clients.splice(clients.indexOf(currentClient),1)
currentClient = undefined
})
})
module.exports = {app: app,server: server}
并在 index.js 中导入
const {app,server} = require('./websocket/expressWsModule')
推荐阅读
- sqlite - sqlite count 1 value based on all previous row and restart count when row value is 0
- javascript - 如何将具有两个键/值对的对象推送到数组中?
- reactjs - 在数组(状态)中添加的待办事项对象不会立即反转
- python - 根据字符串出现、相似性加入两个数据框
- javascript - 如何用 http 请求的响应填充数组?
- javascript - 需要来自另一个 js 文件的数据时,验证代码失败。但是在同一个文件中有效 - 为什么?
- for-loop - 比较具有重复输入值的两个文件
- python - Anaconda 3:无法创建菜单
- r - 加入 sf object 和 tibble 后数据加载速度极慢,这是怎么回事?
- php - 如何从 MySQL 列中获取最大值