夏普没有及时 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
        }
     }