ESP32CAM MQTT传图时Express路由返回旧数据问题如何解决
ESP32CAM图像传输接口返回旧数据修复方案
问题场景
- 硬件端:ESP32CAM摄像头模块每3秒通过MQTT向Node.js(Express)后端发送一次图像Base64数据
- 后端:监听MQTT消息,提供
/img接口给前端返回图像数据 - 前端:每3秒发起AJAX请求拉取
/img接口数据,渲染到页面img标签 - 异常现象:MQTT消息回调内(标注number2位置)每次都能打印最新图像数据,但接口请求触发的路由内(标注number1位置)永远返回第一次收到的旧数据,前端图像无法更新
问题根因
代码逻辑错误:将app.get("/img")路由的注册逻辑写在了MQTT消息的监听回调内部
- Express框架的路由匹配规则是「先注册先匹配」,同路径的路由只有第一个注册的会生效,后续重复注册的同路径路由不会被执行
- 每次收到MQTT消息就会新注册一个
/img路由,但请求永远命中第一次注册的路由,闭包捕获的是第一次收到的旧obj值,所以永远返回旧数据
修复代码
后端app.js修改
核心逻辑:把路由注册移到MQTT回调外部,用全局变量存储最新的图像数据,收到MQTT消息时只更新全局变量即可。
// 全局变量存储最新收到的图像数据,设置初始默认值 let latestImageData = "no image yet"; // 路由只在服务启动时注册一次,绝对不要放在事件回调里重复注册 app.get("/img", function(req, res) { res.set("Content-Type", "application/json"); res.json({ data: latestImageData }); console.log("接口请求返回数据:", latestImageData); // 原number1位置,每次请求打印最新值 }); client.on("message", async (topic, message) => { if (topic === "JPG") { // 收到新的图像数据只更新全局变量 latestImageData = message.toString(); console.log("收到MQTT新图像数据:", latestImageData); // 原number2位置,每次收消息打印最新值 } })
前端代码优化(修复冗余逻辑)
原前端代码重复给img标签赋值,简化后逻辑如下:
$(function() { const timer = setInterval(function() { console.log("发起图像拉取请求"); $.ajax({ url: "http://你的服务IP:3000/img", type: "GET", cache: false, error: function(request, status, error) { console.log(`请求错误,状态码:${request.status},错误信息:${error}`); }, success: function(res) { // 直接给img标签设置src即可,不需要重复操作DOM $("#imguri").attr("src", res.data); console.log("前端收到最新图像数据"); } }); }, 3000); });
内容的提问来源于stack exchange,提问作者dla
相关产品推荐
相关产品推荐

