如何等待返回Promise数组的Promise?S3桶下载问题
问题分析与解决方案
核心问题
downloadBucketRaw函数逻辑错误:
你用了s3.listObjectsV2的回调模式,但async函数不会等待回调执行,且回调内返回的promises数组无法被外层函数捕获——外层实际返回的是 S3 请求对象,而非 Promise 数组,导致Promise.all无法正常工作。downloadFileFromS3函数存在两处问题:- 同时使用
getObject的回调和 Promise 模式,冗余且易引发错误; fs.createWriteStream传入的是item对象({Bucket, Key}),会导致本地文件名变成[object Object],完全不符合预期;file.promise()仅表示 S3 对象数据获取完成,但本地文件写入流可能还未结束,直接返回会导致提前判定“下载完成”。
- 同时使用
修正后的代码
1. 完善文件下载函数(推荐使用 stream.pipeline 处理流)
const { pipeline } = require('stream/promises'); const fs = require('fs'); async function downloadFileFromS3(item) { // 创建S3读取流和本地写入流 const readStream = s3.getObject(item).createReadStream(); const writeStream = fs.createWriteStream(item.Key); // 用Key作为本地文件路径 // 使用pipeline处理流,自动处理错误与完成事件 await pipeline(readStream, writeStream); }
2. 修正存储桶遍历函数
async function downloadBucketRaw(bucket, prefix) { // 使用Promise版本的listObjectsV2,await等待结果返回 const listResult = await s3.listObjectsV2({ Bucket: bucket, Prefix: prefix }).promise(); // 过滤空文件,生成所有下载任务的Promise数组 const downloadPromises = listResult.Contents .filter(element => element.Size > 0) .map(element => downloadFileFromS3({ Bucket: bucket, Key: element.Key })); return downloadPromises; }
正确使用方式
// 等待所有下载任务完成 const promises = await downloadBucketRaw('your-bucket-name', 'your-prefix'); await Promise.all(promises);
或者可以直接在 downloadBucketRaw 内返回 Promise.all(downloadPromises),简化调用:
async function downloadBucketRaw(bucket, prefix) { const listResult = await s3.listObjectsV2({ Bucket: bucket, Prefix: prefix }).promise(); const downloadPromises = listResult.Contents .filter(element => element.Size > 0) .map(element => downloadFileFromS3({ Bucket: bucket, Key: element.Key })); return Promise.all(downloadPromises); // 直接返回所有任务完成的Promise } // 调用时只需await这一步 await downloadBucketRaw('your-bucket-name', 'your-prefix');
内容的提问来源于stack exchange,提问作者David Marciel
相关产品推荐
相关产品推荐

