我正在执行一个功能,该功能可从输入文件字段将图像上传到AWS,然后将图像URL和名称保存到mongoDB。我正在使用NodeJS和MongoDB。这是我的示例:

uploadFile(req, res, next) {

 let files = req.files;
 let images = [];


  files.file.forEach((file) => {

    uploadToAWS(file.path, {}, function(err, img) {

    if (err) { throw err; }

        // add path and name to images array

        images.push({
          path: img[0].url,
          name: img[0].name,
        });
    });
  });
    // Here the promises should resolve and save to MongoDB the array images
 },


每次循环遍历元素时,我没有填充到数据库,而是填充了数组images,然后将其保存到DB。

最佳答案

您可以使用Bluebird的promisify
uploadToAWS()返回承诺而不是进行回调(您也可以在没有promisify的情况下很容易地做到这一点,但是它很有用),因为如果要使用Promise.all等,使用返回承诺的函数要容易得多。建议使用回调的函数,然后建议使用Async模块来管理控制流。

当您分配uploadToAWS()时,您将可以执行以下操作:

let promises = files.file.map(file => uploadToAWS(file.path, {}));


然后,您将可以使用:

Promise.all(promises)
  .then((imgs) => {
    // everything succeeded
  }).catch((error) => {
    // there was an error
  });


或者,如果您使用的是异步/等待:

try {
  let imgs = await Promise.all(promises);
  // everything succeeded
} catch (error) {
  // there was an error
}


现在,只要有imgs,它就是uploadToAWS()返回的对象数组(或者严格地说,是在所有元素都已解析后由uploadToAWS()返回的承诺的分辨率值数组)。

您可以使用该数组创建另一个数组,例如images

let images = imgs.map(img => ({
  path: img[0].url,
  name: img[0].name,
});


要么:

let images = imgs.map(img => ({
  path: img.url,
  name: img.name,
});


取决于uploadToAWS()实际返回的内容,因为您未指定。

但是请记住,发生错误时,您将需要通过删除不再需要的上传文件来从中恢复。

08-15 14:27