Express+WebSocket实现实时商品表格 点击发送无响应问题求助
WebSocket实时商品列表故障修复
核心故障原因
- 发送按钮位于
<form>标签内,未指定type="button"时默认行为是触发表单提交刷新页面,点击后socket.emit逻辑还未执行页面就已重载,服务端无法接收到商品上报消息,仅能打印初始连接日志。 - 原有逻辑存在三个体验缺陷:一是每次接收商品都生成带重复表头的独立表格,页面结构冗余;二是服务端未存储历史商品,新接入用户无法看到之前提交的商品记录;三是缩略图仅输出文本URL,未渲染为图片,不符合功能预期。
分步修复代码
1. HTML部分调整
给按钮添加type="button"阻断默认表单提交,提前固定表格结构,补全Bootstrap基础样式类:
<div class="container mt-3 bg-dark"> <h1 class="text-center text-primary">Ingrese datos</h1> <form class="text-light"> <div class="form-group"> <label for="title"><b>Producto</b></label> <input id="title" type="text" name="title" class="form-control"> </div> <div class="form-group"> <label for="price"><b>Precio</b></label> <input id="price" type="number" name="price" class="form-control"> </div> <div class="form-group"> <label for="thumbnail"><b>Thumbnail</b></label> <input id="thumbnail" type="text" name="thumbnail" class="form-control"> </div> <button id="send" type="button" class="btn btn-primary mt-2">Postear</button> </form> <h2 class="text-center text-danger mt-4">Historial</h2> <div id="output"> <table class="table table-dark"> <thead> <tr class="text-warning"> <th>Title</th> <th>Price</th> <th>Thumbnail</th> </tr> </thead> <tbody id="product-list"></tbody> </table> </div> </div>
2. 前端JS逻辑调整
在点击事件中增加默认行为阻断兜底,渲染时仅向表格主体追加商品行,增加新连接时的历史商品拉取逻辑,补全缩略图渲染、空值校验、提交后清空输入框的基础交互:
const socket = io(); const titleInput = document.getElementById("title") const priceInput = document.getElementById("price") const thumbnailInput = document.getElementById("thumbnail") const sendBtn = document.getElementById("send") const productContainer = document.getElementById("product-list") sendBtn.addEventListener("click", function(e){ e.preventDefault(); const title = titleInput.value.trim(); const price = priceInput.value.trim(); const thumbnail = thumbnailInput.value.trim(); if(!title || !price || !thumbnail){ alert('请填写完整商品信息'); return; } socket.emit("products", {title, price, thumbnail}); titleInput.value = ''; priceInput.value = ''; thumbnailInput.value = ''; }); // 监听实时新增商品 socket.on("products", function (data) { const row = document.createElement('tr'); row.innerHTML = ` <td>${data.title}</td> <td>$${data.price}</td> <td><img src="${data.thumbnail}" style="max-width: 80px; max-height: 80px; object-fit: cover;" alt="${data.title}"></td> `; productContainer.appendChild(row); }) // 监听连接初始化时的历史商品列表 socket.on("init-product-list", function (list) { list.forEach(data => { const row = document.createElement('tr'); row.innerHTML = ` <td>${data.title}</td> <td>$${data.price}</td> <td><img src="${data.thumbnail}" style="max-width: 80px; max-height: 80px; object-fit: cover;" alt="${data.title}"></td> `; productContainer.appendChild(row); }); })
3. 服务端JS逻辑调整
增加历史商品存储数组,新用户连接时主动推送全量历史商品,收到新商品时先入存储再广播给所有连接用户:
const path = require("path") const express = require("express") const app = express() app.set("port", process.env.PORT || 8080) app.use(express.static(path.join(__dirname, "public"))) const server = app.listen(app.get("port"), ()=>{ console.log("server on port", app.get("port")) }) const SocketIO = require("socket.io") const io = SocketIO(server) // 存储全量商品历史 const productStore = []; io.on("connection", (socket)=>{ console.log("new connection", socket.id) // 新连接建立后推送历史商品 socket.emit("init-product-list", productStore); socket.on("products", (data) => { productStore.push(data); // 广播新商品到所有客户端 io.emit("products", data); }) })
注意:确认你的HTML页面中已经正确引入了Socket.IO客户端脚本,否则
io()会直接报错,脚本引入地址默认和服务端同域时为<script src="/socket.io/socket.io.js"></script>,需要放在你自己编写的前端JS之前引入。
内容的提问来源于stack exchange,提问作者Moebiuz
相关产品推荐
相关产品推荐

