无法弄清楚如何将数据异步推送到数组

Posted

技术标签:

【中文标题】无法弄清楚如何将数据异步推送到数组【英文标题】:Can't figure out how to push data to array asynchronously 【发布时间】:2021-06-25 11:29:02 【问题描述】:

这是我编写的一个函数,用于检索我存储在 S3 存储桶中的文件的元数据。

它将存储桶中所有文件的键存储在一个数组中,然后遍历该数组以获取每个单独文件的元数据。问题是我存储值的元数据数组总是空的。

我在值被推入数组的位置之后立即输入了一个打印语句,并且该数组似乎填充得很好,但是当我在该循环之外打印它时它打印为空。

我发现这是因为元数据是异步获取的,并且数组显示为空,因为我在它实际填充值之前打印它。但是我似乎无法弄清楚如何将值异步存储在数组中。一些帮助将不胜感激。

exports.allMetadata = (req, res) => 

    const params = 
        Bucket: env.Bucket
    
    var metadata = [];
    s3.listObjectsV2(params, (err, data) => 
        if (err) 
            console.log(err, err.stack);
            res.send("error -> "+ err);
         else 
            var contents = data.Contents;
            contents.forEach(content => 
                const params1 = 
                    Bucket: env.Bucket,
                    Key: content.Key
                ;
                s3.headObject(params1, (err, data) => 
                    if (err) 
                        console.log(err, err.stack);
                        res.send("error -> "+ err);
                     else 
                        metadata.push(data.Metadata);
                        console.log(metadata); //Prints fine
                    
                );
            );
            console.log(metadata); //Shows empty here
            //res.send(metadata);
        
    );

【问题讨论】:

您是否尝试过在异步函数调用前添加等待?因为它是异步的,所以它会跳过这些调用,以后只会得到响应,除非你告诉它在继续之前等待响应。 @StewartR 看起来那些调用不会返回承诺,所以 await 不会做太多... @StewartR 添加等待不起作用。我对 javascript 很陌生,但我还没有完全理解 async/await。作为我的第一个项目,我的工作场所让我陷入了困境,我感觉自己快要淹死了。 您可以使用const data = await s3.headObject(params1).promise();将其更改为承诺 【参考方案1】:

正如你所说,s3.headObject 是一个异步操作,所以你需要等待它们才能将响应发送给客户端:

exports.allMetadata = (req, res) => 
  const params = 
    Bucket: env.Bucket
  

  s3.listObjectsV2(params, (err, data) => 
    if (err) 
      console.log(err, err.stack)
      res.send('error -> ' + err)
      return
    

    var contents = data.Contents
    const promiseArray = contents.map(content => 
      const params1 = 
        Bucket: env.Bucket,
        Key: content.Key
      
      return readS3Meta(params1)
    )

    // WARN: the array should be not HUGE
    Promise.all(promiseArray)
      .then((allMetadata) => 
        console.log(allMetadata)
        res.send(allMetadata)
      )
      .catch(err => 
        res.send('error -> ' + err)
      )
  )


function readS3Meta (params1) 
  return new Promise((resolve, reject) => 
    s3.headObject(params1, (err, data) => 
      if (err) 
        console.log(err, err.stack)
        reject(err)
        return
      
      resolve(data.Metadata)
    )
  )


【讨论】:

顺便说一句,S3 headObject 方法已经有 .promise() 为您返回承诺。

以上是关于无法弄清楚如何将数据异步推送到数组的主要内容,如果未能解决你的问题,请参考以下文章

从异步回调函数将对象推送到本地数组

无法使用带有 DCE 管道的异步 RPC 将数据推送到服务器

如何在javascript中打印元素异步推送到它的数组?

Vuejs 无法推送到嵌套数组

如何在没有回调地狱的情况下加载图像?

如何将promise的返回值推送到数组中? [重复]