如何用async/await优化Cloudinary上传API,解决数据库提前执行问题
问题根源
你代码里的Cloudinary图片上传是异步操作,但数据库保存、页面重定向是同步执行的。当执行到userItem.save()时,上传图片的回调函数还没跑完,cardImage和urlArray都还是初始的空值,所以数据库里存的就是空数据。
解决办法:用Promise+async/await把异步流程串起来
Cloudinary的upload方法如果不传回调,会返回Promise,咱们可以用async/await等所有上传完成后,再执行数据库操作。修改后的代码如下:
const upload = multer({ storage: multer.diskStorage({ destination: "./public/uploads", filename: (req, file, cb) => cb(null, file.originalname), }), }); const apiRouter = nc({ onNoMatch(req, res) { res.status(405).json({ error: `method ${req.method} not allowed` }); }, }); const arrayOfImages = upload.fields([ { name: "cardImage", maxCount: 1 }, { name: "images", maxCount: 5 }, ]); // 把路由处理函数改成async函数,支持await apiRouter.post(arrayOfImages, async (req, res) => { try { const urlArray = []; let cardImage = ""; const imagesArray = req.files["images"] || []; // 兼容没传images的情况 // 等待单张cardImage上传完成 const cardUploadResult = await cloudinary.uploader.upload( req.files["cardImage"][0].path, { folder: "cardImages" } ); cardImage = cardUploadResult.secure_url; fs.unlinkSync(req.files["cardImage"][0].path); // 批量上传images,用Promise.all等所有上传完成 const imageUploadPromises = imagesArray.map(async (imageFile) => { const uploadResult = await cloudinary.uploader.upload( imageFile.path, { folder: "Images" } ); fs.unlinkSync(imageFile.path); return uploadResult.secure_url; }); // 把所有上传后的URL存入urlArray urlArray.push(...await Promise.all(imageUploadPromises)); // 现在所有图片都上传完了,再存数据库 dataBaseConnection(); const userItem = new Item({ shortDescription: req.body.shortDescription, longDescription: req.body.longDescription, price: req.body.itemPrice, cardImage: cardImage, images: urlArray, }); await userItem.save(); // 等待数据库保存完成 console.log("your product has been added to database."); res.redirect("/dashboard"); } catch (err) { // 统一处理所有错误,避免程序挂掉 console.error(err); res.status(500).json({ error: "Failed to upload images and save item" }); } }); export default apiRouter; export const config = { api: { bodyParser: false, // Disallow body parsing, consume as stream }, };
关键修改点
- 把路由处理函数改成
async,这样内部可以用await等待异步操作 - Cloudinary上传不再传回调,改用
await等单个上传完成 - 多张图片上传用
map生成Promise数组,再用Promise.all一次性等所有上传完成,拿到所有URL - 数据库保存也用
await,确保数据存成功再重定向 - 加了
try/catch捕获所有错误,避免意外崩溃
这样就能保证所有图片上传完成、URL都存进数组后,再执行数据库操作,解决urlArray为空的问题。
内容的提问来源于stack exchange,提问作者Kamran
相关产品推荐
相关产品推荐

