React前端向Node.js后端传递businessImages数组为空问题
React前端上传图片后,Node后端接收的businessImages数组为空的问题
我用React做前端、Node.js做后端开发时遇到一个问题:把vendor对象发送到后端后,后端打印的businessImages数组是空的,但前端打印该对象时,businessImages明明已经填充了内容。相关代码如下:
前端React代码
const handleSubmit = async (e) => { e.preventDefault(); if (businessImages.length > 15) { alert("You've selected too many images for your business"); setBusinessImages([]); } else { const formDataBusinessImages = new FormData(); const formDataProfilePicture = new FormData(); vendor = { name: name.current.value, email: email.current.value, mobileNumber: mobileNumber.current.value, businessAddress: businessAddress.current.value, mainService: selectedService, subServive: selectedSubService, businessImages: [], aboutBusiness: aboutBusiness.current.value, minPrice: minPrice.current.value, maxPrice: maxPrice.current.value, featured: featured, }; formDataProfilePicture.append("file", profilePicture); formDataProfilePicture.append( "upload_preset", process.env.REACT_APP_CLOUDINARY_KEY ); try { await axios .post( "https://api.cloudinary.com/v1_1/devign/image/upload", formDataProfilePicture ) .then((res) => { console.log("Profile pic uploaded"); vendor.profilePicture = res.data.secure_url; }); } catch (err) { console.log(err); } businessImages.map(async (image) => { formDataBusinessImages.append("file", image); formDataBusinessImages.append("upload_preset", process.env.REACT_APP_CLOUDINARY_KEY); try { await axios .post( "https://api.cloudinary.com/v1_1/devign/image/upload", formDataBusinessImages ) .then((res) => { vendor.businessImages.push(res.data.secure_url); }); } catch (err) { console.log(err); } }); handleUpload(vendor); } }; const handleUpload = async (uploadData) => { try { await axios.post("/auth/register", uploadData); } catch (err) { console.log(err); } };
后端Node.js代码
router.post("/register", async (req, res) => { const newVendor = new Vendor({ name: req.body.name, email: req.body.email, mobileNumber: req.body.mobileNumber, businessAddress: req.body.businessAddress, mainService: req.body.mainService, subService: req.body.subService, profilePicture: req.body.profilePicture, businessImages: [], minPrice: req.body.minPrice, maxPrice: req.body.maxPrice, featured: req.body.featured, }); try { newVendor.businessImages.push(req.body.businessImages); console.log(req.body.businessImages, req.body.profilePicture); const vendor = await newVendor.save(); res.status(200).json("Successfully registered"); } catch (err) { console.log(err); } });
问题原因
- 异步操作未等待完成:
businessImages.map中的异步上传请求还没执行完,handleUpload(vendor)就已经被调用,此时vendor.businessImages还没被填充。map不会等待异步回调完成,直接继续执行后续代码。 - 后端赋值错误:
newVendor.businessImages.push(req.body.businessImages)会把整个数组作为单个元素推入,即使前端传了正确数组,后端存储的也是嵌套数组。
修复方案
前端代码修改
用Promise.all等待所有图片上传完成后再发送请求,同时避免复用FormData导致的请求异常:
const handleSubmit = async (e) => { e.preventDefault(); if (businessImages.length > 15) { alert("You've selected too many images for your business"); setBusinessImages([]); return; } let vendor = { name: name.current.value, email: email.current.value, mobileNumber: mobileNumber.current.value, businessAddress: businessAddress.current.value, mainService: selectedService, subServive: selectedSubService, businessImages: [], aboutBusiness: aboutBusiness.current.value, minPrice: minPrice.current.value, maxPrice: maxPrice.current.value, featured: featured, }; // 上传头像 const formDataProfilePicture = new FormData(); formDataProfilePicture.append("file", profilePicture); formDataProfilePicture.append("upload_preset", process.env.REACT_APP_CLOUDINARY_KEY); try { const profileRes = await axios.post( "https://api.cloudinary.com/v1_1/devign/image/upload", formDataProfilePicture ); vendor.profilePicture = profileRes.data.secure_url; } catch (err) { console.log(err); } // 批量上传业务图片,用Promise.all等待全部完成 const imageUploadTasks = businessImages.map(async (image) => { const formData = new FormData(); formData.append("file", image); formData.append("upload_preset", process.env.REACT_APP_CLOUDINARY_KEY); try { const res = await axios.post( "https://api.cloudinary.com/v1_1/devign/image/upload", formData ); return res.data.secure_url; } catch (err) { console.log(err); return null; } }); // 收集所有上传成功的图片URL const uploadedUrls = await Promise.all(imageUploadTasks); vendor.businessImages = uploadedUrls.filter(url => url !== null); // 确保所有图片上传完成后,再发送到后端 await handleUpload(vendor); }; const handleUpload = async (uploadData) => { try { await axios.post("/auth/register", uploadData); } catch (err) { console.log(err); } };
后端代码修改
直接赋值businessImages,避免错误的push操作:
router.post("/register", async (req, res) => { try { const newVendor = new Vendor({ name: req.body.name, email: req.body.email, mobileNumber: req.body.mobileNumber, businessAddress: req.body.businessAddress, mainService: req.body.mainService, subService: req.body.subService, profilePicture: req.body.profilePicture, businessImages: req.body.businessImages || [], minPrice: req.body.minPrice, maxPrice: req.body.maxPrice, featured: req.body.featured, }); console.log(req.body.businessImages, req.body.profilePicture); const vendor = await newVendor.save(); res.status(200).json("Successfully registered"); } catch (err) { console.log(err); res.status(500).json("Registration failed"); } });
内容的提问来源于stack exchange,提问作者Curran-C
相关产品推荐
相关产品推荐

