夏普没有及时 return 图像
Sharp doesn't return the image in time
我迷失了我的 async/awaits 和承诺链。
我正在尝试创建一个包含图像的数组,这些图像将存储在我的服务器上,然后将它们的位置作为链接传递以填充 MySQL 数据库。但是,图像创建 confirmation/links 在数据库保存完成之前不会返回。我认为问题出在我在不同函数中链接的 sharp 命令,但我不知道如何让主代码等待它们。
这是我的控制器代码。我正在使用 Multer 和内存存储来缓冲上传的图像。我使用 Express-Validator 来清理和验证代码:
// saveTrail controller: [validation/sanitization, function]
exports.saveTrail = [
/* lots of validation on other parts of the code */
// Points of Interest validation
body().custom((value, { req }) => {
// Add the files back in to the req.body so that they can be treated normally in validation
const files = req.files.POI_image;
if (files) value.POI_files = files;
// Check to ensure all existing arrays are of the same length
return checkLengthOfObjectArrays(value, "POI");
}).withMessage("POI arrays must be the same length").bail().custom((value) => {
// reassemble the object array and attach it to the req.body (with file information)
value.POI = makeObjectArray(value, "POI");
return true;
}),
body("POI").optional(),
body("POI.*.files").exists().custom((value, { req }) => {
// check valid mime types
const mimetypeArr = value.mimetype.split("/");
return (
mimetypeArr[0] === "image" &&
VALID_IMAGE_TYPES.indexOf(mimetypeArr[1]) > -1
);
})
.withMessage(`Files must be of type: .${VALID_IMAGE_TYPES.join(", .")}`),
/* more validation/sanitization on the other POI fields */
// The actual function!
async (req, res) => {
try {
const body = req.body;
/* handle validation errors */
/* create the new trail */
// Make Point of Interest array
// images will be stored at /public/images/<Trail ID>/<POI || Hazard>/
if (body.POI) {
await body.POI.forEach(async (point) => {
const link = await getPOIImageLinks(trail.trailId, point.files);
point.trailId = trail.trailId;
point.image = link;
console.log("Point\n", point); // <-- this line shows up AFTER the response is sent
});
console.log("body.POI: ", body.POI); // <-- this shows the trailId, but not image, before the response is sent (This is where I would save to the DB)
}
res.status(201).json(body.POI);
return;
} catch (err) {
res.status(500).json({ error: err.message });
return;
}
},
];
// This is the function that manipulates the image and saves it
async function getPOIImageLinks(trailId, file) {
try {
// ensure filesystem exists for save
const path = SAVE_DIRECTORY + trailId + "/POI/";
await ensureDirExists(path); // <-- this shows up where it is expected
const { buffer, originalname } = file;
const { fileName } = getFileName(originalname);
const link = `${path}${fileName}.webp`;
await sharp(buffer)
.resize(RESIZE) // RESIZE is an imported settings object
.webp({ quality: 75 })
.toFile(link)
.then(info => {
console.log("Sharp info:", info); // <-- this shows up before the point output, but after the data has been resent. I think this is the location of my problem
})
.catch((err) => {
throw new Error(err);
});
return link;
} catch (err) {
console.log(err);
}
}
我认为这与 sharp.tofile()
命令不等待有关。我不知道如何打破这条链,文档没有帮助 (https://sharp.pixelplumbing.com/api-constructor),我只是没有足够的经验在 promise 链和 async/await.
之间切换
提前致谢!
James 是正确的,答案在 。我完全是在寻找错误的解决方案。
问题是我用 foreach
循环调用它。我需要用 for ... of
循环调用我的函数。
if (body.POI) {
for (const point of body.POI) { // <--- the fix
const link = await getPOIImageLinks(trail.trailId, point.files);
point.trailId = trail.trailId;
point.image = link;
console.log("Point\n", point); // <-- this line shows up properly now
}
}
我迷失了我的 async/awaits 和承诺链。
我正在尝试创建一个包含图像的数组,这些图像将存储在我的服务器上,然后将它们的位置作为链接传递以填充 MySQL 数据库。但是,图像创建 confirmation/links 在数据库保存完成之前不会返回。我认为问题出在我在不同函数中链接的 sharp 命令,但我不知道如何让主代码等待它们。
这是我的控制器代码。我正在使用 Multer 和内存存储来缓冲上传的图像。我使用 Express-Validator 来清理和验证代码:
// saveTrail controller: [validation/sanitization, function]
exports.saveTrail = [
/* lots of validation on other parts of the code */
// Points of Interest validation
body().custom((value, { req }) => {
// Add the files back in to the req.body so that they can be treated normally in validation
const files = req.files.POI_image;
if (files) value.POI_files = files;
// Check to ensure all existing arrays are of the same length
return checkLengthOfObjectArrays(value, "POI");
}).withMessage("POI arrays must be the same length").bail().custom((value) => {
// reassemble the object array and attach it to the req.body (with file information)
value.POI = makeObjectArray(value, "POI");
return true;
}),
body("POI").optional(),
body("POI.*.files").exists().custom((value, { req }) => {
// check valid mime types
const mimetypeArr = value.mimetype.split("/");
return (
mimetypeArr[0] === "image" &&
VALID_IMAGE_TYPES.indexOf(mimetypeArr[1]) > -1
);
})
.withMessage(`Files must be of type: .${VALID_IMAGE_TYPES.join(", .")}`),
/* more validation/sanitization on the other POI fields */
// The actual function!
async (req, res) => {
try {
const body = req.body;
/* handle validation errors */
/* create the new trail */
// Make Point of Interest array
// images will be stored at /public/images/<Trail ID>/<POI || Hazard>/
if (body.POI) {
await body.POI.forEach(async (point) => {
const link = await getPOIImageLinks(trail.trailId, point.files);
point.trailId = trail.trailId;
point.image = link;
console.log("Point\n", point); // <-- this line shows up AFTER the response is sent
});
console.log("body.POI: ", body.POI); // <-- this shows the trailId, but not image, before the response is sent (This is where I would save to the DB)
}
res.status(201).json(body.POI);
return;
} catch (err) {
res.status(500).json({ error: err.message });
return;
}
},
];
// This is the function that manipulates the image and saves it
async function getPOIImageLinks(trailId, file) {
try {
// ensure filesystem exists for save
const path = SAVE_DIRECTORY + trailId + "/POI/";
await ensureDirExists(path); // <-- this shows up where it is expected
const { buffer, originalname } = file;
const { fileName } = getFileName(originalname);
const link = `${path}${fileName}.webp`;
await sharp(buffer)
.resize(RESIZE) // RESIZE is an imported settings object
.webp({ quality: 75 })
.toFile(link)
.then(info => {
console.log("Sharp info:", info); // <-- this shows up before the point output, but after the data has been resent. I think this is the location of my problem
})
.catch((err) => {
throw new Error(err);
});
return link;
} catch (err) {
console.log(err);
}
}
我认为这与 sharp.tofile()
命令不等待有关。我不知道如何打破这条链,文档没有帮助 (https://sharp.pixelplumbing.com/api-constructor),我只是没有足够的经验在 promise 链和 async/await.
提前致谢!
James 是正确的,答案在
问题是我用 foreach
循环调用它。我需要用 for ... of
循环调用我的函数。
if (body.POI) {
for (const point of body.POI) { // <--- the fix
const link = await getPOIImageLinks(trail.trailId, point.files);
point.trailId = trail.trailId;
point.image = link;
console.log("Point\n", point); // <-- this line shows up properly now
}
}