Node.js for循环异步写入文件报错排查求助
解决异步改写后的ReferenceError与未处理Promise拒绝问题
先给你拆解下遇到的两个核心问题,再给你修正后的代码和详细说明:
为什么会出现这些错误?
1. ReferenceError: result is not defined
你在test函数的循环里写了let result = await Promise.resolve(i);,这就踩坑了——这行代码重新声明了和函数参数同名的result变量,而且因为let的暂时性死区特性,在当前循环块里,result被提前声明但还没赋值的时候,你就用console.log(result)去访问它,直接触发了ReferenceError。
2. 未处理Promise拒绝
- 你的
test是async函数,但调用的时候只加了.then(),没加.catch()兜底错误; - 里面的
fs.writeFile是老的回调式API,没有转成Promise也没做await处理,导致错误没法被async函数捕获,自然就出现了未处理的Promise拒绝警告。
另外,原代码内存占用高的本质是并发执行了大量文件写入,内存里堆了太多Buffer;你原来的异步改写根本没控制并发,等于换汤不换药,得改成串行或者有限并发才能真正解决内存问题。
修正后的完整代码
// 先把fs的writeFile转成Promise版,方便用await const fs = require('fs').promises; const db = require('./your-db-module'); // 记得替换成你的实际数据库模块 async function writeImages(result) { console.log(result[0]); console.log(`Total images to process: ${result.length}`); // 用for...of配合await实现串行写入,降低内存压力 for (const [index, row] of result.entries()) { console.log(`Starting to process image ${index}`); try { const { imageID, imageBlob } = row; // 划重点:原代码的编码处理是错的!Blob本身是Buffer,直接写入就行 await fs.writeFile(`public/images/shareImg/${imageID}`, imageBlob); console.log(`✅ File written successfully: ${imageID} (index: ${index})`); } catch (err) { console.error(`❌ Failed to write file ${row.imageID}:`, err); } } } // 数据库查询逻辑 db.query("SELECT imageID, imageBlob FROM sys.users_image;", async function (err, result, fields) { console.log("Downloading images from database..."); if (err) { console.error('Database query failed:', err); return; } try { await writeImages(result); console.log('🎉 All images have been processed!'); } catch (err) { console.error('❌ Error during image processing:', err); } });
关键修改点说明
- 修复ReferenceError:删掉了循环里那个画蛇添足的
let result = await Promise.resolve(i);,改用解构赋值取imageID和imageBlob,彻底避免变量名冲突。 - 解决未处理Promise拒绝:
- 用
fs.promises.writeFile替代回调式API,直接转成Promise,配合await可以轻松捕获错误; - 在
writeImages内部加了try/catch,单个文件写入失败不会中断整个流程; - 调用
writeImages时也加了try/catch,兜底整个流程的错误。
- 用
- 降低内存占用:
- 用
for...of+await实现串行写入,每次只处理一个文件,写完再处理下一个,不会一次性把所有Buffer都堆在内存里; - 修正了原代码的编码错误:
imageBlob本身就是Buffer,直接写入就行,原代码转成binary字符串再用base64编码写入,不仅会导致文件损坏,还额外浪费内存。
- 用
额外优化建议
如果你的数据库返回的结果集特别大(比如上万条),建议用数据库的流式查询(比如mysql2的stream API),边查边写,不用一次性把所有数据都读到内存里;要是想兼顾速度和内存,可以用p-limit这类库实现有限并发(比如同时写5个文件),找到适合你服务器的平衡点。
内容的提问来源于stack exchange,提问作者jamep37912
相关产品推荐
相关产品推荐

