在这里,我尝试返回文件数组,但返回未定义

时间:2020-07-23 16:12:56

标签: javascript node.js amazon-web-services amazon-s3

在下面的函数中,我尝试返回文件,但是在搜索文件时返回未定义,它返回未定义。在执行搜索并获取S3对象的地方,并准备对象数组以进一步发送电子邮件。

        const send_email = async(data) => {
          try {
         
            const data_attachment = await get_S3_files(batch_key);
        
            console.log(data_attachment)
            
          } catch (error) {
            console.log(error)
          }
        }
    
    const get_S3_files = (data) => {


 return new Promise((resolve, reject) => {
      var params = {
          Bucket: S3_bucket,
          Delimiter: '',
          Prefix: `${data}/`
      }
      var files = []
      s3.listObjects(params, function (err, data) {
          if (err) throw err;
          if (data.Contents.length) {
              for (const row of data.Contents) {
  
                  await s3.getObject({ Bucket: 'name', Key: row.Key }, function (err, data) {
                      if (err) {
                          console.log('S3 Get Object Error', err)
                          reject(err)
                      } else {
                          console.log(data)
                          files.push({
                              filename: data.Body,
                              content: data.Metadata.file_name,
                          })
  
                      }
                  })
              }
          }
      });
      
      resolve(files);
  })
}

编辑-

  1. 已删除等待
  2. 保留函数部分的返回结果

问题:执行功能键之前其返回的空数组。 enter image description here

有人可以在这里帮助吗?我在做什么错了?

3 个答案:

答案 0 :(得分:0)

您从错误的地方回来。您的return语句位于s3.listObjects函数内部。 return files;应该在关闭函数之前在下面一行。但是,它仍然无法正常工作。您必须保证该功能。

const get_S3_files = (data) => {
    return new Promise((resolve, reject) => {
        var params = {
            Bucket: 'name',
            Delimiter: '',
            Prefix: `${data}/`
        }
        var files = []
        s3.listObjects(params, async function (err, data) {
            if (err) throw err;
            if (data.Contents.length) {
                for (const row of data.Contents) {
    
                    await s3.getObject({ Bucket: 'name', Key: row.Key }, function (err, data) {
                        if (err) {
                            console.log('S3 Get Object Error', err)
                            reject(err)
                        } else {
                            console.log(data)
                            files.push({
                                filename: data.Body,
                                content: data.Metadata.file_name,
                            })
    
                        }
                    })
                }
            }

            resolve(files);
        });
    })
}

答案 1 :(得分:0)

问题出在竞争状况上。它甚至在等待数组填充之前就返回。

我认为此解决方案可能有效。

const send_email = async (data) => {
  try {
    const data_attachment = await get_S3_files(batch_key);

    console.log(data_attachment);
  } catch (error) {
    console.log(error);
  }
};

const get_S3_files = (batch_key) => {
  return new Promise((resolve, reject) => {
    var params = {
      Bucket: S3_bucket,
      Delimiter: "",
      Prefix: `${batch_key}/`,
    };

    s3.listObjects(params, async function (err, data) {
      var files = [];
      if (err) throw err;
      if (data.Contents.length) {
        await Promise.all(
          data.Contents.map((row) => {
            return new Promise((resolve, reject) => {
              s3.getObject({ Bucket: S3_bucket, Key: row.Key }, (err, data) => {
                if (err) return reject(err);
                files.push({
                  filename: data.Body,
                  content: data.Metadata.file_name,
                });
                return resolve(data);
              });
            });
          })
        );
      }
      return resolve(files);
    });
  });
};

答案 2 :(得分:0)

下面的代码片段不一定能解决原始问题,但是如果OP开放以对其代码进行一些大的更改,那么我认为该解决方案将在不影响原始功能的情况下完美地工作。

const get_S3_files = async (data) => {

    var params = {
        Bucket: 'name',
        Delimiter: '',
        Prefix: `${data}/`
    }
    var files = []
    await s3.listObjects(params, async function (err, data) {
        if (err) throw err;
        if (data.Contents.length) {
            for (const row of data.Contents) {
                try {
                    const dataContent = await s3.getObject({ Bucket: 'name', Key: row.Key }).promise();
                    files.push({
                        filename: dataContent.Body,
                        content: dataContent.Metadata.file_name,
                    })
                } catch(err) {
                    console.log('S3 Get Object Error', err);
                }
            }
        }
        return files;
    });
}

在任何地方使用回调都会使代码不可读。我建议您使用promise()和s3 sdk的方法将响应转换为承诺。

类似地,您可以将listObjects方法转换为Promise。它将使代码更具可读性。

注意:我从代码末尾添加了一些变量,请确保根据您的代码上下文对其进行更改。