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

Node.js中Express+Socket.io按序发送文件数据时的图片重复问题

问题根源与修复方案

核心问题分析

  1. 全局变量污染:buffer、img、img_path未用let/const声明,属于全局作用域。多个send函数异步执行时,后一次调用会覆盖前一次的变量值,导致最终发送的都是最后一次的图片数据。
  2. 不可靠的异步等待:用setTimeout(100ms)等待图片读取完全依赖时间预估,一旦文件读取耗时超过100ms,会发送空buffer;读取太快则可能被后续异步读取覆盖。
  3. forEach不支持异步等待:files.forEach(async file => { ... })中的await不会阻塞循环,所有send函数几乎同时执行,加剧变量污染。
  4. 错误处理缺失:图片读取、JSON解析的错误未被捕获,也未正确reject Promise。

修复后的完整代码

const fs = require('fs').promises;
const path = require('path');

async function send(file) {
    try {
        // 读取并解析JSON文件
        const jsonString = await fs.readFile(path.join(dir, file), 'utf8');
        const jsonData = JSON.parse(jsonString);
        
        let buffer = "";
        let img = false;
        const imgBasePath = path.join(dir, jsonData.number);
        
        // 优先读取jpg,不存在再尝试png
        try {
            buffer = await fs.readFile(`${imgBasePath}.jpg`);
            img = true;
        } catch (err) {
            try {
                buffer = await fs.readFile(`${imgBasePath}.png`);
                img = true;
            } catch (err2) {
                // 两种图片都不存在时保持初始值
            }
        }
        
        const data = {
            number: jsonData.number,
            image: img,
            buffer: buffer.toString('base64')
        };
        
        socket.emit('data', data);
        console.log(`已发送文件: ${file}`);
    } catch (err) {
        console.error(`处理文件${file}出错:`, err);
        throw err;
    }
}

async function files() {
    try {
        const files = await fs.readdir(dir);
        // 用for...of确保逐个处理,等待前一个完成再执行下一个
        for (const file of files) {
            if (path.extname(file) === '.json') {
                await send(file);
            }
        }
    } catch (err) {
        console.error('读取目录出错:', err);
    }
}

files();

关键修复点说明

  • 使用fs.promises:将回调式文件读取转为Promise风格,配合await精准等待异步操作完成,彻底抛弃不可靠的setTimeout。
  • 变量作用域隔离:所有变量用let/const声明在send函数内部,每次调用创建独立变量实例,避免被后续调用覆盖。
  • for...of替代forEach:for...of支持await,确保文件按顺序处理,不会并行触发send导致变量冲突。
  • 路径安全处理:用path.join拼接路径,避免因操作系统路径分隔符差异引发错误。
  • 完善错误捕获:每个异步操作包裹try/catch,错误会被打印并向上抛出,便于排查问题。

内容的提问来源于stack exchange,提问作者PioterSky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:35:20