js asyn c ожидание выполнения функции - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть node.js сервер. И мне надо хранить файлы по указанному c API. Моя функция для него:

exports.bootcampPhotoUpload = asyncHandler(async (req, res, next) => {
  ...
  const fileNames = [];
  files.forEach((item) => {
    item.name = `photo_${bootcamp._id}${path.parse(item.name).ext}`;
    item.mv(`${process.env.FILE_UPLOAD_PATH}/${item.name}`, async err => {
      console.log(item.name); // logs on console second and shows fileName
      fileNames.push(item.name);
    });
  });

  console.log(fileNames); // logs on console firstly and shows []
  const updated = await Bootcamp.findByIdAndUpdate(req.params.id, { photo: fileNames });
  console.log(fileNames); // logs on console third and shows [filenames]
  res.status(200).json({
    success: true,
    data: fileNames
  });
});

И на моей модели сохранено:

{
  photo: []
}

item объект:

{ name: 'photo_2020-04-18 14.08.56.jpeg',
  data:
   <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff db 00 43 00 04 03 03 04 03 03 04 04 03 04 05 04 04 05 06 0a 07 06 06 06 06 0d 09 0a 08 ... >,
  size: 208920,
  encoding: '7bit',
  tempFilePath: '',
  truncated: false,
  mimetype: 'image/jpeg',
  md5: 'f8714b4e2135c3873c939a9464ea380a',
  mv: [Function: mv]
}

Для загрузки файла я использую express-fileupload. Существует проблема с выполнением async/await. Как я могу сохранить его правильно?

1 Ответ

0 голосов
/ 23 апреля 2020

Две проблемы здесь.

  1. Ваша mv функция работает в асинхронном режиме c и основана на обратном вызове, поэтому вы не можете напрямую использовать await.
  2. Даже если мы переключим ее на обещание, ожидание выиграно ' Мы не можем работать с forEach, как мы ожидаем.

Для первого мы можем использовать нормальное значение для l oop. А для второго мы можем использовать util.promisify для преобразования вашей mv функции в обещание на основе. Проверьте здесь для выполнения c на util.promisify.

Попробуйте следующий код,

const util = require('util');

const fileNames = [];

for (let i = 0; i < files.length; i++) { // 1. for loop here to support await in code block
    const item = files[i];
    item.name = `photo_${bootcamp._id}${path.parse(item.name).ext}`;
    try {
        await util.promisify(item.mv)(`${process.env.FILE_UPLOAD_PATH}/${item.name}`)   // 2. Promisify here so we can await
        console.log(item.name);
        fileNames.push(item.name);
    } catch (err) {
        // handle err
    }
}

console.log(fileNames);

Примечание: util.promisify может быть медленнее, поэтому он будет будет лучше, если вы найдете альтернативный метод / версию mv, которая уже основана на обещаниях.

...