如何实现多异步文件上传并同时将两个新生成URL写入数据库
解决思路
- 将单个文件的上传逻辑封装为独立的Promise函数,上传成功后resolve返回下载URL,失败则reject抛出错误
- 收集所有存在的文件对应的上传Promise,通过
Promise.all批量等待所有上传任务完成 - 所有上传完成后一次性拿到两个文件的下载URL,仅执行一次数据库写入操作
重构后可直接使用的代码
// 封装单个文件上传逻辑,返回Promise const uploadFile = (file) => { return new Promise((resolve, reject) => { const uploadTask = storage.ref(`documents/${file.name}`).put(file); uploadTask.on( "state_changed", (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log(`Progress: ${progress}%`); if (snapshot.state === "RUNNING") { console.log(`Progress: ${progress}%`); } }, (error) => { console.log(error.code); reject(error); }, async () => { const downloadURL = await uploadTask.snapshot.ref.getDownloadURL(); resolve(downloadURL); } ) }) } export function postAPI(payload) { return async (dispatch) => { dispatch(setLoading(true)); try { const uploadTasks = []; // 按顺序加入第一个文件的上传任务,没有文件则直接返回空字符串 uploadTasks.push(payload.firstDoc !== "" ? uploadFile(payload.firstDoc) : Promise.resolve("")); // 按顺序加入第二个文件的上传任务,没有文件则直接返回空字符串 uploadTasks.push(payload.secondDoc !== "" ? uploadFile(payload.secondDoc) : Promise.resolve("")); // 等待所有上传任务完成,按顺序拿到两个文件的下载URL const [firstDocURL, secondDocURL] = await Promise.all(uploadTasks); // 统一写入数据库,仅生成一条记录 await db.collection("articles").add({ data: payload.data, firstDoc: firstDocURL, secondDoc: secondDocURL, }); } catch (err) { console.error("操作失败:", err); } finally { // 无论成功失败都重置loading状态 dispatch(setLoading(false)); } } }
关键改动说明
- 解决了原代码上传两个文件时会生成两条重复数据库记录的问题,全程仅执行一次
db.add - 自适应0/1/2个文件的上传场景,无需额外分支判断
- 完全保留了原有的上传进度打印逻辑,没有丢失原有功能
- 增加了全局异常捕获,避免上传失败后loading状态一直为true的问题
内容的提问来源于stack exchange,提问作者Matthew Bussen
相关产品推荐
相关产品推荐

