如何等待含Firebase异步上传的.map()执行完毕后再执行db.push?
这个问题的核心是异步操作的顺序问题——你用map遍历图片数组时,每个图片的上传和URL获取都是异步的(返回Promise),但map本身是同步执行的,它不会等待这些异步操作完成就继续往下走了,所以后面的db.push()自然会在图片还没传完、URL还没收集全的时候就执行了。
解决的关键是用Promise.all()来等待所有图片上传+获取URL的异步操作全部完成,然后再执行数据库推送。具体实现如下:
修改后的代码
UploadForm(event) { event.preventDefault(); const db = firebase.database().ref('app').child('cards'); const userId = this.props.user; // 表单获取的数据 const titel = this.titelInput.value; const grabtiefe = this.grapTiefeVonInput.value +" - " + this.grapTiefeBisInput.value; // 修正了原代码中遗漏的.value const transportbreite = this.transportbreiteVonInput.value + " - " + this.transportbreiteBisInput.value; const transporthoehe = this.transporthoeheVonInput.value + " - " + this.transporthoeheBisInput.value; const gewicht = this.GewichtdesArtikelsInput.value; const preis = this.priceInput.value; const desc = this.descInput.value; const adresse = this.props.address; const ort = this.props.ort; const mobil = this.props.mobil; const festnetz = this.props.festnetz; const pictures = this.state.pictures[0]; const keys = Object.keys(pictures); // 把每个图片的上传+获取URL包装成Promise,收集到数组中 const uploadPromises = keys.map((key) => { const picture = pictures[key]; // 复用Storage引用,避免重复创建 const storageRef = firebase.storage().ref('images') .child(`artikelimgaes/${userId}`) .child('artikel/') .child(titel) .child(picture.name); // 返回一个Promise:完成上传后直接获取下载URL return storageRef.put(picture) .then(() => storageRef.getDownloadURL()) .catch(err => { console.error(`图片 ${picture.name} 上传失败:`, err); throw err; // 抛出错误让Promise.all统一处理 }); }); // 等待所有图片上传完成,拿到完整的URL数组 Promise.all(uploadPromises) .then((imageUrls) => { // 更新state存储URL数组 this.setState({ Arr: imageUrls }); // 执行数据库推送(直接用imageUrls,不用依赖state的异步更新) const coordinaten = this.state.cords; const mainImage = imageUrls[0]; return db.push({ grabtiefe: grabtiefe, transportbreite: transportbreite, transporthoehe: transporthoehe, cardHeading: titel, cardPreis: preis, cardDesc: desc, gewicht: gewicht, address: adresse, ort: ort, gemietet: 0, cords: coordinaten, mobil: mobil, festnetz: festnetz, imageArr: imageUrls, imageUrl: mainImage, gebiet: this.state.gebiet, bundesland: this.state.bundesland, uid: userId, }); }) .then(() => { // 数据库推送完成后再跳转 this.setState({ redirect: true }); }) .catch(err => { console.error('整个上传流程失败:', err); // 这里可以添加用户提示,比如弹出上传失败的消息 }); }
关键说明
- Promise.all的作用:它会等待数组中所有Promise都成功resolve后,才会进入后续的
then回调,此时imageUrls就是完整的图片URL数组。 - 复用Storage引用:避免上传后重复创建相同的Storage引用,减少冗余代码。
- 避免依赖state的异步更新:
setState是异步操作,所以直接用Promise.all返回的imageUrls,而不是去读取this.state.Arr,防止数据不一致。 - 错误处理:添加了全局
catch捕获整个流程中的错误,方便调试和给用户反馈。
内容的提问来源于stack exchange,提问作者HarryTgerman
相关产品推荐
相关产品推荐

