0

在下面的代码中,当我在调试模式下运行时,在这一行有一个断点:content.push(data.Body.toString());我可以看到数据被插入到content数组中。

但是,当我正常运行代码时,content返回为空。

我怎样才能让它填充阵列以供下游使用?

var params = { Bucket: "thebucket", Prefix: "theprefix/" }
var content = [];
function getS3Data()
{    
var s3 = new aws.S3();
s3.listObjects(params, function (err, data) 
{        
    if (err) throw err; // an error occurred
    else 
    {            
        var i;
        for (i = 0; i < data.Contents.length; i++)              
        {
            var currentValue =  data.Contents[i];
            if(currentValue.Key.endsWith(params.Prefix) == false) 
            {
                var goParams = { Bucket: params.Bucket, Key: currentValue.Key };                   
                s3.getObject(goParams, function(err, data) 
                {                        
                    if (err) throw err; //error                        
                    content.push(data.Body.toString());       
                });
            };
        };            
    }//else
});//listObjects
}//getS3Data

getS3Data();

console.log(content); //prints empty here when run in non-debug.
4

2 回答 2

0

行:
console.log(content)
在行之前执行:
content.push(data.Body.toString());

您作为第二个参数传递的函数s3.listObjects将异步执行。如果要注销,content则需要在回调函数含义内进行:

s3.listObjects(params, function (err, data) {        
    if (err) throw err;
    else {            
        // ...
        console.log(content)
    }
});

更好的方法是实现getS3Datawith ,Promise这样您就可以在确定完成对象列表后运行代码。

function getS3Data() {
    return new Promise((resolve, reject) => {
        if (err) {
            reject(err)
        } else {
            const promises = []
            for (const i = 0; i < data.Contents.length; i++) {
                const currentValue = data.Contents[i];
                if (currentValue.Key.endsWith(params.Prefix) == false) {
                    const goParams = { Bucket: params.Bucket, Key: currentValue.Key };
                    promises.push(new Promise((res, rej) => {
                        s3.getObject(goParams, function (err, data) {
                            if (err) {
                                rej(err); //error
                            } else {
                                res(data.Body.toString());
                            }                        
                        });
                    }));
                }
            }
            Promise.all(promises).then(resolve);
        }
    });
}

getS3Data()
    .then(result => { // this will actually be `content` from your code example
        console.log(result);
    }).catch(error => {
        console.error(error);
    })
于 2018-07-25T20:23:17.573 回答
0

Node.js 的文档有一个与您遇到的问题非常相似的示例:

问题的出现是因为变量content没有getS3Data在完成后立即设置,因为它是一个异步函数。content稍后会设置。但是您的调用console.log(content);将在完成后立即执行getS3Data,因此此时content尚未设置。

您可以通过添加额外的日志来测试:

s3.getObject(goParams, function(err, data) 
{                        
    if (err) throw err; //error                        
    content.push(data.Body.toString());
    console.log("Content has been assigned");
});

然后将底部更改为:

getS3Data();
console.log("getS3Data has finished", content);

您可能会按以下顺序收到消息:

getS3Data has finished
Content has been assigned
于 2018-07-25T20:15:58.867 回答