Next.js中MinIO Client流转JSON异常:仅返回首项或空数组
问题:Next.js中MinIO listObjectsV2返回数据异常的排查与修复
我尝试在Next.js中创建REST API接口,通过MinIO Client的listObjectsV2方法获取存储桶内的对象列表并返回完整JSON,但遇到问题:直接将流数据传入resolve时,仅能得到第一个对象;尝试将对象转为数组返回时,却得到空数组[]。以下是我的两段测试代码及对应的控制台日志:
第一段代码(直接返回流)
export async function GET() { return new Promise(resolve => { const objectsStream = s3Client.listObjectsV2('node', '', true, '') objectsStream.on('data', function (obj) { console.log(obj) resolve(NextResponse.json((obj))) }) /* Error Hand */ objectsStream.on('error', function (e) { resolve(NextResponse.json(e)) }) }) }
控制台日志
{ name: '00002.png', lastModified: 2023-12-28T15:44:26.762Z, etag: 'f1684b805ec19d1cd993a50173acb64b', size: 13664646 } { name: '00040.png', lastModified: 2023-12-28T15:44:39.300Z, etag: '23efca60e3ca26165f1bb12a9e19d223', size: 5197315 }
返回结果
仅返回第一个对象:
{ "name": "00002.png", "lastModified": "2023-12-28T15:44:26.762Z", "etag": "f1684b805ec19d1cd993a50173acb64b", "size": 13664646 }
第二段代码(转为数组返回)
export async function GET() { return new Promise(resolve => { const objectsStream = s3Client.listObjectsV2('node', '', true, '') objectsStream.on('data', function (obj) { const arr = Object.assign([], obj); console.log(arr) resolve(NextResponse.json((JSON.stringify(arr)))) }) objectsStream.on('error', function (e) { resolve(NextResponse.json(e)) }) }) }
控制台日志
[ name: '00002.png', lastModified: 2023-12-28T15:44:26.762Z, etag: 'f1684b805ec19d1cd993a50173acb64b', size: 13664646 ] [ name: '00040.png', lastModified: 2023-12-28T15:44:39.300Z, etag: '23efca60e3ca26165f1bb12a9e19d223', size: 5197315 ]
返回结果
返回空数组:[]
错误原因分析
第一段代码的问题
- Promise的
resolve()只能执行一次,第一次data事件触发时就调用了resolve,后续的对象数据根本没有机会被处理,所以只返回第一个对象。 listObjectsV2返回的是流,data事件会分批触发,每一次事件传递一个对象,不能在单次data事件里直接结束Promise。
第二段代码的问题
Object.assign([], obj)是把对象的属性复制到数组中,但对象的键(如name、lastModified)不是数组的数字索引,JSON序列化时会忽略这些非数字索引的属性,所以最终得到空数组。- 同样犯了在单次
data事件里调用resolve的错误,只处理了第一个对象,没有收集所有数据。
修复后的代码
export async function GET() { return new Promise((resolve, reject) => { const objectsStream = s3Client.listObjectsV2('node', '', true, ''); const objectsList = []; // 收集每一个返回的对象 objectsStream.on('data', (obj) => { objectsList.push(obj); console.log(obj); }); // 流结束时,返回完整的对象列表 objectsStream.on('end', () => { resolve(NextResponse.json(objectsList)); }); // 错误处理:用reject抛出异常,同时设置500状态码 objectsStream.on('error', (e) => { reject(NextResponse.json(e, { status: 500 })); }); }); }
修复说明
- 初始化空数组
objectsList,在每一次data事件触发时,将对象推入数组,完成所有数据的收集。 - 监听流的
end事件,当所有数据接收完毕后,再调用resolve返回完整的对象列表JSON。 - 错误处理改用
reject,符合Promise的规范,同时返回500状态码明确标识服务器错误。
内容的提问来源于stack exchange,提问作者Load Galax
相关产品推荐
相关产品推荐

