fs.readdirSync无法读取文件夹文件?Node.js图片处理类问题排查
问题原因及解决方案
核心问题分析
forEach不支持异步等待
你在getImages里用了forEach(async (link, i) => { ... }),但forEach本质是同步遍历,它不会等待内部的异步操作完成——不管里面写了多少await,forEach都会直接遍历完所有元素后立刻返回。这导致getImages虽然标记了async,但实际会在所有下载任务启动前就结束,saveImages里的await等于无效,uploadImages会在图片还没下载完成(甚至还没开始写入磁盘)时就执行,自然读不到文件。流写入未等待完成
就算解决了forEach的问题,pipe(fs.createWriteStream(fileLocation))是异步写入操作:await axios(...)只代表请求的响应头和部分数据已拿到,不代表文件已经完全写入磁盘。这时候去读目录,文件可能还处于写入中状态,依然会返回空数组。
修复代码
1. 修复getImages函数
用map+Promise.all替代forEach,同时将流写入封装为Promise等待完成:
export const getImages = async ( links: string[], folder: string, extra?: string ) => { // 用map生成异步任务数组,Promise.all等待所有任务完成 await Promise.all(links.map(async (link, i) => { const fileLocation = path.resolve( folder, extra ? extra : "", `image${i}.jpeg` ); const response = await axios({ method: "get", url: extractImageUrl(link), responseType: "stream", }); // 封装流写入为Promise,等待finish事件确认文件写入完成 await new Promise<void>((resolve, reject) => { response.data .pipe(new ExifTransformer()) .pipe(fs.createWriteStream(fileLocation)) .on("finish", () => resolve()) .on("error", (err) => reject(err)); }); })); };
2. 简化主函数调用(可选)
不需要混用await和then,直接顺序执行更清晰:
const main = async (url: string) => { const id = uid(5); const IH = new imageHandler(id, imageFolder); await IH.saveImages(data?.images); IH.uploadImages(); };
额外排查建议
- 临时测试:可以在
uploadImages前加await new Promise(resolve => setTimeout(resolve, 2000)),如果延迟后能读到文件,就坐实了异步操作未等待的问题。 - 路径校验:在
getImages里打印fileLocation,和uploadImages里的jobFolder对比,确保两者路径完全一致(避免相对路径/绝对路径混用导致的目录不匹配)。 - 权限检查:确认程序拥有目标目录的读写权限(不过你手动能看到文件,大概率不是这个问题)。
内容的提问来源于stack exchange,提问作者XooT
相关产品推荐
相关产品推荐

