如何等待AWS Lambda中的asynchronous操作?

我正在尝试在S3中处理上传的文件。 由于getObject是asynchronous主函数在处理完成之前结束,并且AWS在3-4秒内杀死lambda。

更糟糕的是,处理方法也有asynchronous操作 – 它使http调用。

在高层次上,我的代码如下所示:

exports.handler = function(event, context) { // Get the object from the event and show its content type var bucket = event.Records[0].s3.bucket.name; var key = event.Records[0].s3.object.key; var params = { Bucket: bucket, Key: key }; s3.getObject(params, function(err, data) { if (err) { ... } else { processFile(data.Body.toString(), 0); console.log("ok"); } }); //need to wait here till processFile is done }; processFile = function(content, start) { ... build url to call http.get(url, function(res) { console.log("Got response: " + res.statusCode + "); processFile(content, start + 1); }); } 

我发现在nodejs中有asynchronous,但不包含在amazon中; 两者都需要('asynchronous')或要求('睡眠)导致错误。

Lambda超时configuration为60秒,但在3-4秒后退出。

不包括async但这并不意味着你不能自己添加它。 只需在本地添加软件包( npm install async ),并在上传Lambda函数之前在ZIP中包含node_modules文件夹。

如果你想单独处理开发依赖项(例如:test, aws-sdk在本地执行你的函数等),你可以将它们添加到你的package.json devDependencies下。 另外,如果你想自动化开发,testing,部署和推广你的代码的过程,这两个回购将变得非常方便。

Grunt例程来testing,打包和部署你的lambdaexpression式

用于运行和部署您的lambda函数的命令行工具

我认为你的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"); } }); 

把Lambda想象成一个可以在一定时间内运行的程序。 你做asynchronous调用的事实是很好的,因为(虚拟)处理器可能会交错这些调用。 但是,如果您的Lambda程序的任何部分比分配的时间花费更长的时间,那么执行将会失败。 这是你做出的妥协,也是亚马逊如何赚钱的方式; 通过卖给你更多的时间或记忆。

要解决这个问题,您可以增加Lambda函数分配的内存。 这不仅增加了你的内存,而且增加了虚拟处理器的速度。 你可以做的另一件事是增加超时。 AWS Lambda现在允许您使用高达512 MB的RAM和长达5分钟的处理时间。 截至这篇文章,这些数字可能已经改变,所以请检查这里的最新限制。 要更改此设置,请转到您的function,然后进行configuration,最后再进行升级。

我手上也有同样的问题。

问题是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)); } } }; 

如果你想使用require('async'); 包装或require('sleep'); 包以及你需要上传你的function,像这样的zip文件:

创build一个部署包(Node.js)

把这个文件夹的所有内容Zip ,就像我在这个问题中解释的那样:

AWS中的MQTT Lambda函数用于Alexa Javascript

关于同步处理,你可以使用require('async'); 通常情况下,只是使用这样的async.seriesfunction:

  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函数将同步工作。

我希望能帮助你。

您可能想改为进行synchronous呼叫; 因为你似乎正在处理你的文件在相同的lambda函数。

如果由于某种原因,你想得到一个callback; 你可以通过直接调用lambda或者通过产生lambda事件的东西来实现。 请注意,lambda函数应该是无状态的; 所以你应该通过所有需要的信息。