I'm lost with my async/awaits and promise chaining.
I am trying to create an array with images that will be stored on my server and then have their location passed as links to populate a MySQL database. However, the image creation confirmation/links aren't being returned before the DB save would be done. I think the problem is with my chained sharp commands in a different function, but I don't know how to make the main code wait on them.
Here is my controller code. I'm using Multer and memory storage to buffer the images uploaded. I use Express-Validator to Sanitize and Validate the code:
// 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);
  }
}
I think this has to do with the sharp.tofile() command not waiting. I don't know how to break up that chain, the documentation isn't helping (https://sharp.pixelplumbing.com/api-constructor) and I just don't have enough experience switching between promise chains and async/await.
Thanks in advance!
