js异步等待功能执行顺序

时间:2020-04-23 05:25:39

标签: javascript async-await

我有node.js个服务器。我应该将文件存储在特定的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-fileuploadasync/await执行存在问题。 如何正确保存它?

1 个答案:

答案 0 :(得分:0)

这里有两个问题。

  1. 您的mv函数是基于异步和回调的,因此您不能直接使用await。
  2. 即使我们将其转变为基于承诺的,await也不会像我们期望的那样与forEach一起使用。

对于第一个,我们可以使用普通的for循环。对于第二个,我们可以使用util.promisifymv函数转换为基于promise。在util.promisify上检查here上的文档。

尝试以下代码,

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的替代方法/版本(已经基于promise)会更好。