我正在使用Lambda / NodeJS在AWS上进行开发。作为对POST请求的响应,我试图返回一个数据对象,该对象带有预签名的URL,可以访问S3上的图像。问题是返回数据,因此实际上是作为API的响应返回的。我知道这是一个异步问题,但到目前为止仍无法解决。非常感谢您的帮助。
我有以下代码:
{
{
docClient.query(dbparams, function (err, data) {
if (err) {
console.log(err);
_response = buildOutput(500, err);
return callback(_response, null);
} else {
dataObj = data.Items;
var createOutput = function (callback) {
async.forEach(dataObj, function (item, callback) {
setObjectUrl(item, function (err, data) {
if (err) {
console.log(err);
}
return callback(undefined, data);
});
});
};
createOutput(function (err, data) {
if (err) {
console.log(err);
}
});
_response = buildOutput(200, data);
return callback(null, _response);
}
});
}
}
function setObjectUrl(data, callback) {
var s3params = {
Bucket: s3Bucket,
Key: 'avatars/' + data.username + '.jpg'
};
S3.headObject(s3params, function (err, metadata) {
if (err && err.code === 'NotFound') {
//console.log('geen url voor deze gebruiker gevonden');
} else {
data["url"] = S3.getSignedUrl('getObject', s3params);
}
return callback(data);
});
}
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
}
答案 0 :(得分:0)
所有异步调用完成后,您需要调用lambda的回调。有一些不同的选项可以修复您的代码,但是我建议您使用Promise和async / await。这样不仅可以使您的代码正常工作,而且还可以使代码更具可读性,并有助于避免回调地狱。
您需要将S3呼叫包装在promise中:
function getObjectUrl(data) {
const s3params = {
Bucket: s3Bucket,
Key: 'avatars/' + data.username + '.jpg'
};
return new Promise((resolve, reject) => {
S3.headObject(s3params, function (err, metadata) {
if (err) {
//handle error
} else {
const signedUrl = S3.getSignedUrl('getObject', s3params);
resolve(signedUrl);
}
});
});
}
之后,您只需要循环调用已承诺的函数即可:
for(let item of data.Items) {
item.url = await getObjectUrl(data);
}
别忘了使您的主要功能异步并配置lambda以使用NodeJS 8.10
答案 1 :(得分:0)
这就是我最终解决它的方式。感谢您的帮助。
const AWS = require('aws-sdk');
const util = require('util');
// Create reference to S3 client
var S3 = new AWS.S3({
region: 'XXXXXXXXXXXX'
apiversion: '2006-03-01'
});
// Lambda provided credentials
let creds = new AWS.EnvironmentCredentials('AWS');
const dynamoConfig = {
credentials: creds,
region: process.env.AWS_REGION
};
const dynamoDB = new AWS.DynamoDB.DocumentClient(dynamoConfig);
const dynamoDBGetAsync = util.promisify(dynamoDB.query).bind(dynamoDB);
// some variables we need
const ddbTable = 'database';
var _response;
var s3Bucket = 'photo-bucket';
module.exports.handler = async (event, context, callback) => {
if (event.resource === '/' && event.httpMethod === "GET") {
const username = event.queryStringParameters.userid;
var params = {
TableName: ddbTable,
IndexName: 'userid-index',
KeyConditionExpression: "#uid = :uid",
ExpressionAttributeNames: {
"#uid": "userid"
},
ExpressionAttributeValues: {
":uid": username
}
};
let result= await dynamoDBGetAsync(params);
for (let item of result.Items) {
if (item.username !== undefined || null) {
item.url = await getObjectUrl(item);
}
}
_response = buildOutput(200, result);
return callback(null, _response);
}
};
function getObjectUrl(data) {
console.log("Data: " +JSON.stringify(data));
const s3params = {
Bucket: s3Bucket,
Key: 'avatars/' + data.username + '.jpg'
};
return new Promise((resolve, reject) => {
S3.headObject(s3params, function (err, metadata) {
console.log('parameters: ' + JSON.stringify(s3params));
if (err && err.code === 'NotFound') {
console.log(JSON.stringify(err));
} else {
const signedUrl = S3.getSignedUrl('getObject', s3params);
console.log(signedUrl);
resolve(signedUrl);
}
});
});
}
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
}