You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

服务器端WebSocket配置求助:nftController中wss变量未定义

问题:nftController中wss变量始终为undefined

配置服务器端WebSocket时,nftController.js中从server.js导入的wss变量始终显示undefined,已确认导入路径和导出逻辑无误,相关代码如下:

server.js

const dotenv = require("dotenv");
const mongoose = require("mongoose");
const app = require("./app");
const WebSocket = require('ws');
const http = require("http");
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });


process.on("uncaughtException", err=>{
  console.log("uncaughtException Shutting down Application");
  console.log(err.name, err.message);
  process.exit(1);
});

dotenv.config({ path: "./config.env" });
const DB = "mongodb+srv://rameez:<PASSWORD>@cluster0.ogku096.mongodb.net/NFTMarketplace?retryWrites=true&w=majority"

mongoose
  .connect(DB, {
    useCreateIndex: true,
    useFindAndModify: false,
    useNewUrlParser: true,
    useUnifiedTopology: false,
  })
  .then((con) => {
    console.log("DB Connection Successfully");
  }) 

console.log(process.env.NODE_ENV);
app.get('/', (req, res) => {
  res.send('Hello, world!');
});

wss.on('connection', (ws) => {
  console.log('New WebSocket connection');
});


const port = process.env.PORT || 4000;
server.listen(port, () => {
  console.log(`App running on port ${port}....`);
});

process.on("unhandledRejection", (err) => {
  console.log("unhandledRejection Shutting down Application");
  console.log(err.name, err.message); 
  server.close(() => {
    process.exit(1);
  });
});

module.exports = { wss };

nftController.js

const { wss }  = require("../server");
const NFT = require("./../models/nftModel");
const APIFeatures = require("./../Utils/apiFeatures");
const catchAsync = require("../Utils/catchAsync");
const AppError = require("../Utils/appError");

console.log("wss", wss);

// Update top 5 NFTs data whenever there is new data
exports.aliasTopNFTs = catchAsync(async (req, res, next) => {
  req.query.limit = "5";
  req.query.sort = "-price";
  req.query.fields = "name,price,seller,image,createAt";
  const features = new APIFeatures(NFT.find(), req.query)
    .filter()
    .sort()
    .limitFields()
    .pagination();
  const nfts = await features.query;
  req.query.nfts = nfts;
  next();
});

const sendUpdatedData = (data) => {
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: 'UPDATE_DATA', data: data }));
    }
  });
}

exports.getAllNfts = catchAsync(async (req, res) => {
  const features = new APIFeatures(NFT.find(), req.query)
    .filter()
    .sort()
    .limitFields()
    .pagination();
  const nfts = await features.query;
  sendUpdatedData(nfts);
  console.log("WSSdata", nfts);

  //SEND QUERY
  res.status(200).json({
    status: "success",
    results: nfts.length,
    data: {
      nfts,
    },
  });
});
解决方案

问题根源

这是模块循环加载导致的初始化顺序问题:server.js中引入了./app,而app.js必然会引入nftController.js(作为路由控制器)。当nftController.js在顶部导入server.js时,server.js的代码还未执行到module.exports = { wss }这一行,此时wss变量尚未被赋值,因此得到undefined。

方法1:拆分WebSocket模块(推荐)

将WebSocket相关逻辑单独抽离成模块,避免循环依赖,同时保证wss实例初始化完成后再被调用:

  1. 创建wsServer.js文件:
const WebSocket = require('ws');

let wssInstance = null;

// 初始化WebSocket服务器
function initWebSocketServer(server) {
  wssInstance = new WebSocket.Server({ server });
  
  wssInstance.on('connection', (ws) => {
    console.log('New WebSocket connection');
  });
  
  return wssInstance;
}

// 获取已初始化的wss实例
function getWebSocketServer() {
  return wssInstance;
}

module.exports = { initWebSocketServer, getWebSocketServer };
  1. 修改server.js,使用新模块初始化wss:
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const app = require("./app");
const http = require("http");
const { initWebSocketServer } = require('./wsServer'); // 导入WebSocket模块

const server = http.createServer(app);
// 初始化WebSocket服务器
initWebSocketServer(server);

// 原有其余代码保持不变...

// 移除原有的module.exports = { wss };
  1. 修改nftController.js,从新模块获取wss实例:
const { getWebSocketServer } = require("../wsServer"); // 替换导入源
const NFT = require("./../models/nftModel");
const APIFeatures = require("./../Utils/apiFeatures");
const catchAsync = require("../Utils/catchAsync");
const AppError = require("../Utils/appError");
const WebSocket = require('ws'); // 补上WebSocket导入,解决OPEN常量问题

const sendUpdatedData = (data) => {
  const wss = getWebSocketServer();
  if (!wss) return; // 防止服务器未完成初始化时调用
  
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: 'UPDATE_DATA', data: data }));
    }
  });
}

// 原有其余代码保持不变...

方法2:延迟导入(临时方案)

如果不想拆分模块,可以在需要使用wss的函数内部动态导入server.js,此时server已完成初始化:

修改nftController.js中的sendUpdatedData函数:

const sendUpdatedData = (data) => {
  const { wss } = require("../server"); // 在函数内部导入
  const WebSocket = require('ws'); // 补上WebSocket导入
  
  if (!wss) return;
  
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: 'UPDATE_DATA', data: data }));
    }
  });
}

该方法虽然简单,但不够优雅,不利于代码维护,仅作为临时解决手段。


内容的提问来源于stack exchange,提问作者The Day Galpu Club

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:17:05