在 Node.js 中,数组在调试中填充得更多,但在正常模式下不填充
Array populated in debug more but not in in normal mode in Node.js
在下面的代码中,当我 运行 处于调试模式并在此行处设置一个断点时: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.
Node.js' 文档中有一个与您遇到的问题非常相似的示例:
问题的出现是因为变量 content
没有在 getS3Data
完成后立即设置,因为它是一个 asynchronous 函数。 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
行:
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)
}
});
更好的方法是使用 Promise
实现 getS3Data
,这样您就可以 运行 在确定对象列表完成后编写代码。
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);
})
在下面的代码中,当我 运行 处于调试模式并在此行处设置一个断点时: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.
Node.js' 文档中有一个与您遇到的问题非常相似的示例:
问题的出现是因为变量 content
没有在 getS3Data
完成后立即设置,因为它是一个 asynchronous 函数。 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
行:
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)
}
});
更好的方法是使用 Promise
实现 getS3Data
,这样您就可以 运行 在确定对象列表完成后编写代码。
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);
})