批量上传1000个对象至Google Cloud Storage仅成功400个,求原因
问题原因与解决方案
核心问题:Promise处理错误
你的代码中存在关键的API使用错误,导致无法正确等待文件写入完成,这是文件丢失的主要原因:
- 回调与Promise的冲突:@google-cloud/storage的
file.save方法是回调优先的设计——如果传入了回调函数,方法会以回调模式执行,不会返回Promise。你当前给save传了() => console.log(...)的回调,所以promises.push(...)实际上是把undefined推入数组,而非异步写入任务的Promise实例。 - 无效的等待逻辑:
Promise.all(promises)处理全是undefined的数组时,会直接立即resolve,不会等待实际的文件写入操作完成。这导致每批50个写入任务还没全部执行完毕,代码就清空数组并继续下一轮循环,甚至脚本结束时还有大量未完成的写入任务被终止,最终只有部分文件成功写入存储桶。
解决方案
修改file.save的调用方式,确保获取到有效的Promise来跟踪异步任务:
方式1:移除回调,改用Promise链式调用处理日志
const writeDocs = async () => { try { const arr = new Array(1000).fill({ test: "test"}); const promises = []; for (let i=0; i < arr.length; i++) { const file = bucket.file(`test/${i}.json`); // 移除回调,用then处理日志 promises.push( file.save(JSON.stringify(arr[i])) .then(() => console.log(`saved JSON document ${i} to storage`)) ); if (promises.length >= 50) { console.log("writing batch. total:", i+1) await Promise.all(promises); promises.length = 0; await sleep(1000); } } if (promises.length) { await Promise.all(promises); } } catch (error) { console.error(error); } }
方式2:封装为async函数,用await简化逻辑
const writeSingleFile = async (index, data) => { const file = bucket.file(`test/${index}.json`); await file.save(JSON.stringify(data)); console.log(`saved JSON document ${index} to storage`); }; const writeDocs = async () => { try { const arr = new Array(1000).fill({ test: "test"}); const promises = []; for (let i=0; i < arr.length; i++) { promises.push(writeSingleFile(i, arr[i])); if (promises.length >= 50) { console.log("writing batch. total:", i+1) await Promise.all(promises); promises.length = 0; await sleep(1000); } } if (promises.length) { await Promise.all(promises); } } catch (error) { console.error(error); } }
关于速率限制的说明
Google Cloud Storage的对象创建速率是公开的,默认单存储桶每秒最多支持1000次对象创建请求。你的每批50个、间隔1秒的执行模式(每秒50次请求)远低于这个限制,所以不是速率限制导致的文件丢失问题。如果后续需要更高并发,可以参考官方的批量操作规范,但当前问题与速率限制无关。
内容的提问来源于stack exchange,提问作者dazzaondmic
相关产品推荐
相关产品推荐

