我正在尝试在S3中处理上传的文件。由于 getObject 是异步主函数在处理完成之前结束,并且AWS在3-4秒内杀死lambda。
更糟糕的是,处理方法中还包含异步操作 - 它会进行http调用。
在高级别,我的代码如下:
remove("/path/to/foo.txt");
我发现nodejs中存在异步但亚马逊不包含它;需要('async')或require('sleep)都会导致错误。
Lambda超时配置为60秒,但它会在3-4秒内退出。
答案 0 :(得分:28)
开发者的生活在不断变化,我们现在在lambda上有NodeJS 8。对于现在看这个的人来说,请查看:
Lambda节点8.10与节点6.10比较: https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/
JS异步的基础知识: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
更多aws sdk示例:https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html
有关wtf的详细信息.promise()方法位于第一个链接:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#promise-property
以下是我对一个基本示例的看法(尝试粘贴到自己的lambda中):
exports.handler = async (event) => {
function wait(){
return new Promise((resolve, reject) => {
setTimeout(() => resolve("hello"), 2000)
});
}
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
return 'exiting'
};

以上产量:
你可以看到它等了12秒而没有杀死我的功能:)
TODO每次等待多件事,使用Promise.all([])这样的语法:
exports.handler = async (event) => {
var uploadPromises = [];
folder.files.forEach(file => {
uploadPromises.push( s3.putObject({
Bucket: "mybucket",
Key: file.name,
Body: file.data
}).promise());
});
await Promise.all(uploadPromises);
return 'exiting'
};
下面的Orignal答案
我手上的问题完全相同。
问题是javascript事件循环是空的,所以Lambda认为它已经完成了。
这就是我解决这个问题的方法。我意识到这不是理想的,我希望有更好的方法,但我不想a)添加库,b)协调lambda调用,或c)切换到另一种语言。
在一天结束时它会起作用。
exports.handler = (event, context, callback) => {
var response;
var callBackCount;
/*
Ensures the javascript event loop is never empty.
This is the key to keeping lambda from exiting early
*/
setInterval(function(){}, 1000);
/*
Tell lambda to stop when I issue the callback.
This is super important or the lambda funciton will always go until it hits the timeout limit you set.
*/
context.callbackWaitsForEmptyEventLoop = false;
//My way of determining when I'm done with all calls
callBackCount = 0;
//My info to return
response = "";
//Various functions that make rest calls and wait for a response
asyncFunction1();
asyncFunction2();
asyncFunction3();
//Same for asyncFunction 2 and 3
function asyncFunction1(){
response += callBackResponseForThisMethod;
returnResponse();
}
function returnReponse(){
callBackCount++;
if(callBackCount == 3){
//Lambda will stop after this as long as context.callbackWaitsForEmptyEventLoop was set to false
callback(null, JSON.stringify(response));
}
}
};

http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
答案 1 :(得分:7)
async
不包括在内,但这并不意味着您无法自行添加。
只需在本地添加包(npm install async
),并在上传Lambda函数之前在ZIP中包含node_modules
文件夹。
如果您想单独处理dev依赖项(例如:test,aws-sdk
以在本地执行您的函数等),您可以在devDependencies
的{{1}}下添加它们。此外,如果您想自动化开发,测试,部署和推广代码的过程,这两个回购将变得非常方便。
Grunt routine to test, package and deploy your lambdas
Command line tool for running and deploying your lambda functions
答案 2 :(得分:5)
我认为你的lambda函数应该以 context.done()调用结束。例如,尝试以这种方式添加它:
s3.getObject(params, function(err, data) {
if (err) {
...
context.done("Error: " + err.stack);
} else {
processFile(data.Body.toString(), 0);
console.log("ok");
context.done(null, "success");
}
});
答案 3 :(得分:5)
将Lambda想象成一个可以在一定时间内运行的程序。您进行异步调用的事实很好,因为(虚拟)处理器可能会交错这些调用。但是,如果Lambda程序的任何部分比分配的时间花费的时间更长,那么执行将失败。这是您做出的妥协,也是亚马逊赚钱的方式;通过卖给你更多的时间或记忆。
要解决这个问题,您可以增加分配Lambda功能的内存。这不仅可以增加RAM,还可以提高虚拟处理器的速度。您可以做的另一件事是增加超时。 AWS Lambda现在允许最多512 MB的RAM和最多5分钟的处理时间。截至本帖子,这些数字可能已更改,因此请检查here以获取最新限制。要更改此设置,请转到您的功能,然后进行配置,最后进入高级。
答案 4 :(得分:5)
使用async / await
let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();
let data;
exports.handler = async (event) => {
try {
data = await lambda.getAccountSettings().promise();
}
catch (err) {
console.log(err);
return err;
}
return data;
};
答案 5 :(得分:4)
如果您还想使用require('async');
打包或require('sleep');
打包,则需要将您的功能上传为zip
这样的文件:
Creating a Deployment Package (Node.js)
Zip
我在这个问题中解释了该文件夹的所有内容:
MQTT in AWS Lambda function for Alexa Javascript
关于同步处理,您可以正常使用require('async');
,只需使用async.series
这样的功能:
async.series([
function(callback) {
// to do the function 1
callback();
},
function(callback) {
// to do the function 2
callback();
},
function(callback) {
// to do the function 3
callback();
}
], function(err) {
// to do the function if any error happens...
if (err) {
//...
}
//....
});
这样lambda
函数将同步工作。
我希望能帮助你。
答案 6 :(得分:0)
您可能想要拨打synchronous
电话;因为您似乎在同一个lambda函数中处理文件。
如果由于某种原因你想要回电;你可以通过直接调用lambda或通过产生lambda事件的东西来做到这一点。请注意,lambda函数应该是无状态的;所以你应该传递所有需要的信息。