异步性问题:为什么函数的第二部分在循环事件结束之前运行



我在Express服务器上有一个更新用户配置文件的路由。在我解析完要更新的数据之前,用户配置文件已经更新。为什么呢

我想更新两个常量:newProfilePicture&newOtherPictures。它们是正确更新的,但在用户更新之后,所以没有用。如何解决这个异步性问题?

以下是功能:

router.post("/upload-images", upload.array("image"), async (req, res) => {
const { userId } = req.body;
try {
if (req.files) {
let newProfilePicture = null;
let newOtherPictures = [];
req.files.forEach(({ path, originalname }) => {
cloudinary.uploader.upload(
path,
{
resource_type: "image",
public_id: `myapp/users/${userId}/${originalname}`,
crop: "scale",
quality: "auto",
},
(err, res) => {
if (err) {
return fs.unlinkSync("./" + path);
}
fs.unlinkSync("./" + path);
if (originalname === "main") {
return (newProfilePicture = res.secure_url);
}
return newOtherPictures.push({
id: originalname,
url: res.secure_url,
});
}
);
});
// THIS PART IS COMPLETE BEFORE THE req.files.forEach IS DONE
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
res.send("upload images success");
}
} catch (err) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});

这是因为cloudinary.uploader.upload()异步运行。由于您提到它没有promise接口,您可以使用NodeJS的util.promise函数将回调转换为promise,因为它是错误优先回调。
const { promisify } = require("util");
const fs = require("fs");
const cloudinaryUpload = promisify(cloudinary.uploader.upload.bind(cloudinary.uploader))
router.post("/upload-images", upload.array("image"), async (req, res) => {
try {
if (!req.files) {
return res.send("no images in the request body");
}
let newProfilePicture = null;
let newOtherPictures = [];
for (const { path, originalName } of req.files) {
try {
const response = await cloudinaryUpload(path, {
resource_type: "image",
public_id: `myapp/users/${userId}/${originalName}`,
crop: "scale",
quality: "auto",
});
await fs.promises.unlink("./" + path);
if (originalname === "main") {
newProfilePicture = response.secure_url;
continue;
}
newOtherPictures.push({
id: originalName,
url: response.secure_url,
});
} catch (error) {
//do what you want if there is an error
//throw error if you want
await fs.promises.unlink("./" + path);
}
}
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
//use User.updateOne() as you don't need the doc back
await User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
return res.send("upload images success");
} catch (error) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});

最新更新