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

Node.js如何实现先删除S3文件再执行MySQL删除操作

问题现象

开发需同时删除S3存储桶图片、对应MySQL数据库记录的API接口,出现执行顺序异常:数据库删除操作先于S3删除执行,S3删除逻辑查询媒体记录时返回null,无法定位待删除的S3文件。
预期执行顺序:删除S3文件 → 删除数据库记录

相关代码

路由层代码

// Router code:
//req.body为ID数组,示例值:[ 213, 214]
//S3删除逻辑
req.body.forEach((mediaId) => {
    mediaService.removeMediaItem(mediaId);
});

//数据库删除逻辑
await recycleBinService.deleteRecycledMedia(req.body);

S3删除业务方法

removeMediaItem逻辑为:根据传入的mediaId查询media表获取文件名,再调用s3Connection.deleteFile删除S3对应文件

const removeMediaItem = async (mediaId) => {
  const image = await _db.findOne("media", { id: mediaId });
  console.log("image: ", image);
  await s3Connection.deleteFile(image.file_name);
};

数据库删除业务方法

deleteRecycledMedia逻辑为:依次执行两条原生SQL,分别删除media表、recycle_bin表中匹配ID的记录

const wheresMedia = _apiDb.orWhere("id", mediaIds);
const wheresRecycle = _apiDb.orWhere("media", mediaIds);

// 按传入顺序执行两条SQL
await _apiDb.doubleRawSql(
`DELETE from media ${wheresMedia}`,
`DELETE from recycle_bin ${wheresRecycle}`
  );
问题根因
  • removeMediaItem是async声明的异步函数,在forEach循环中调用时没有添加await等待执行完成,forEach本身也不支持等待内部异步任务,循环会快速发起所有S3删除的异步调用后,直接进入后续的数据库删除逻辑。
  • 数据库删除操作无需等待S3删除任务全部完成,会提前删除media表中的对应记录,此时尚未执行完的S3删除逻辑再查询media表,就会获取到null结果。
修复方案
  • 替换原有forEach无等待调用的写法,使用Promise.all等待所有S3删除任务全部执行完成后,再执行数据库删除操作,保证执行顺序符合预期。
    修复后的路由代码:
// 等待所有S3文件删除任务全部完成
await Promise.all(req.body.map((mediaId) => mediaService.removeMediaItem(mediaId)));
// S3操作全部执行完毕后,再执行数据库删除
await recycleBinService.deleteRecycledMedia(req.body);
  • 增加空值容错:在removeMediaItem方法中增加查询结果判空逻辑,避免记录不存在时触发空指针报错,同时打印异常日志方便排查。
const removeMediaItem = async (mediaId) => {
  const image = await _db.findOne("media", { id: mediaId });
  console.log("image: ", image);
  if (!image) {
    console.error(`对应媒体记录不存在,mediaId:${mediaId}`);
    return;
  }
  await s3Connection.deleteFile(image.file_name);
};

内容的提问来源于stack exchange,提问作者jimbus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:51:19