AWS Lambda returns 'null' 经过 forEach 循环将多个文件保存在 s3 存储桶中
AWS Lambda returns 'null' after going through a forEach loop of saving multiple files in s3 bucket
我有一个 AWS Lambda 函数。它遍历数组列表,这是一个 URL 数组,并保存它们的屏幕截图并将它们放在 s3 中。我如何 return 此函数的输出是 screenshotLinks 数组,其中包含保存在 s3 中的文件的所有链接?最后还是用了回调函数,结果returns null!我想要回调函数输出保存在 screenshotLinks 数组中的所有 s3 文件链接。
exports.handler = (event, context, callback) => {
desktopLinks.forEach(function (url, index) {
https.request(url, function(res) {
var data = new Stream();
res.on('data', function(chunk) {
// Agregates chunks
data.push(chunk);
});
res.on('end', function() {
var body = data.read();
// Once you received all chunks, send to S3
var currentLink = links[index];
var linkAddress = encodeURIComponent(currentLink);
var slashPosition = getPosition(currentLink, '/', 3)+1;
var linkName = currentLink.substr(slashPosition, currentLink.length)
var params = {
Bucket: bucket,
Key: completeDate + '/screenshots/' + linkName + '.png',
Body: body
};
s3.putObject(params, function(err, data, callback) {
if (err) {
console.error(err, err.stack);
} else {
bunch = params.Bucket + '/' + params.Key;
screenshotLinks.push(bunch);
}
});
});
}).end();
})
callback(null, screenshotLinks)
};
您的代码是事件驱动/异步的,这意味着您在屏幕截图链接被填充之前调用回调。
节点 http.ClientRequest.end() 方法完成发送请求,但这并不意味着响应已被接收和处理,因为这是由异步事件处理程序完成的。然而,回调是在调用 request.end() 之后立即执行的,也就是在请求被触发之后,因此 screenshotLinks 是空的。
您需要从传递给 s3.putObject 的回调中执行回调。我建议您向回调传递一个 response/result 对象,该对象指示 putObject 是否成功并包含与之相关的 url 以及错误消息或屏幕截图链接,例如像这样:
s3.putObject(params, function(err, data, callback) {
var s3Response;
s3Response.url = url;
if (err) {
s3Response.success = false;
s3Response.error = err;
console.error(err, err.stack);
} else {
bunch = params.Bucket + '/' + params.Key;
s3Response.success = true;
s3Response.screenshotLink = bunch;
}
callback(null, s3Response);
});
我建议您使用 8.10 节点运行时。
参考:https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/
那么你的切入点应该是:
export async function <function_name>(event) {}
然后:
let s3 = new AWS.S3({ region: process.env.AWS_REGION, apiVersion: '2006-03-01' });
let params=
{
Bucket: /* a path to bucket (string) */,
Key: name /* string */,
Body: /* supported types (Buffer, Typed Array, Blob, String, ReadableStream) */,
ACL: 'public-read',
ContentType: 'image/png'
};
try
{
let s3Response = await s3.upload(params).promise();
// if succceed
console.log(`File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`);
}
catch (ex) // if error occured
{
console.error(ex);
}
我有一个 AWS Lambda 函数。它遍历数组列表,这是一个 URL 数组,并保存它们的屏幕截图并将它们放在 s3 中。我如何 return 此函数的输出是 screenshotLinks 数组,其中包含保存在 s3 中的文件的所有链接?最后还是用了回调函数,结果returns null!我想要回调函数输出保存在 screenshotLinks 数组中的所有 s3 文件链接。
exports.handler = (event, context, callback) => {
desktopLinks.forEach(function (url, index) {
https.request(url, function(res) {
var data = new Stream();
res.on('data', function(chunk) {
// Agregates chunks
data.push(chunk);
});
res.on('end', function() {
var body = data.read();
// Once you received all chunks, send to S3
var currentLink = links[index];
var linkAddress = encodeURIComponent(currentLink);
var slashPosition = getPosition(currentLink, '/', 3)+1;
var linkName = currentLink.substr(slashPosition, currentLink.length)
var params = {
Bucket: bucket,
Key: completeDate + '/screenshots/' + linkName + '.png',
Body: body
};
s3.putObject(params, function(err, data, callback) {
if (err) {
console.error(err, err.stack);
} else {
bunch = params.Bucket + '/' + params.Key;
screenshotLinks.push(bunch);
}
});
});
}).end();
})
callback(null, screenshotLinks)
};
您的代码是事件驱动/异步的,这意味着您在屏幕截图链接被填充之前调用回调。
节点 http.ClientRequest.end() 方法完成发送请求,但这并不意味着响应已被接收和处理,因为这是由异步事件处理程序完成的。然而,回调是在调用 request.end() 之后立即执行的,也就是在请求被触发之后,因此 screenshotLinks 是空的。
您需要从传递给 s3.putObject 的回调中执行回调。我建议您向回调传递一个 response/result 对象,该对象指示 putObject 是否成功并包含与之相关的 url 以及错误消息或屏幕截图链接,例如像这样:
s3.putObject(params, function(err, data, callback) {
var s3Response;
s3Response.url = url;
if (err) {
s3Response.success = false;
s3Response.error = err;
console.error(err, err.stack);
} else {
bunch = params.Bucket + '/' + params.Key;
s3Response.success = true;
s3Response.screenshotLink = bunch;
}
callback(null, s3Response);
});
我建议您使用 8.10 节点运行时。
参考:https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/
那么你的切入点应该是:
export async function <function_name>(event) {}
然后:
let s3 = new AWS.S3({ region: process.env.AWS_REGION, apiVersion: '2006-03-01' });
let params=
{
Bucket: /* a path to bucket (string) */,
Key: name /* string */,
Body: /* supported types (Buffer, Typed Array, Blob, String, ReadableStream) */,
ACL: 'public-read',
ContentType: 'image/png'
};
try
{
let s3Response = await s3.upload(params).promise();
// if succceed
console.log(`File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`);
}
catch (ex) // if error occured
{
console.error(ex);
}