Promise写入文件完成后无法读取文件内容的问题排查
问题描述
我写了一段代码从S3下载文件到本地目录,之后读取文件内容并打印到控制台。我把文件复制逻辑封装进Promise,想用await确保文件写入完成后再执行读取操作,但运行代码后,文件能正确复制,读取部分却只打印空行;即使不删除已复制的文件再次运行,结果仍是空行。不过若将读取打印代码移至Promise上方,却能正常打印内容。刚接触Promise和异步编程,不清楚问题出在哪里,代码如下:
const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const fs = require('fs'); (async function copyAndPrintFile() { const S3Bucket = "ExampleBucketName"; const S3File = "ExampleFileName" // Copy file from S3 to local directory const readParams = { Bucket: S3Bucket, Key: S3File, ResponseContentType: "text/plain" }; const copyFilePromise = new Promise((resolve, reject) =>{ const file = fs.createWriteStream(S3File); s3.getObject(readParams).createReadStream().pipe(file); resolve(console.log("File has been written")); }) await copyFilePromise; // Read contents of new file and print it to the console let data = fs.readFileSync(S3File, 'utf-8'); console.log(data); })();
问题原因
你的Promise里resolve调用得太早了——pipe是异步操作,S3的数据流还在往本地文件写的时候,你就直接执行了resolve,导致await提前结束,此时文件其实还没写完,所以后续用fs.readFileSync读到的是空内容。
而把读取代码移到Promise上方时,你读的是之前运行已经完整写入的文件,所以能正常打印内容。
修复方案
需要监听本地写流的finish事件,在这个事件触发时(表示文件已经完全写入)再调用resolve;同时还要监听error事件处理传输或写入中的错误,避免Promise一直处于pending状态。修改后的代码如下:
const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const fs = require('fs'); (async function copyAndPrintFile() { const S3Bucket = "ExampleBucketName"; const S3File = "ExampleFileName" const readParams = { Bucket: S3Bucket, Key: S3File, ResponseContentType: "text/plain" }; const copyFilePromise = new Promise((resolve, reject) =>{ const file = fs.createWriteStream(S3File); const readStream = s3.getObject(readParams).createReadStream(); // 监听写入完成事件 file.on('finish', () => { console.log("File has been written"); resolve(); }); // 监听错误事件,处理读写过程中的异常 readStream.on('error', reject); file.on('error', reject); readStream.pipe(file); }) await copyFilePromise; let data = fs.readFileSync(S3File, 'utf-8'); console.log(data); })();
关键修改点:
- 给写流添加
finish事件监听,确保文件完全写入后才resolve - 给读流和写流都添加
error事件监听,出现错误时调用reject,避免Promise挂起 - 把
resolve的调用移到finish事件回调里,不再提前触发
内容的提问来源于stack exchange,提问作者Thorium
相关产品推荐
相关产品推荐

