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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:33:25