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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:45:51