为啥 AWS Lambda 函数在回调函数执行之前完成?
Posted
技术标签:
【中文标题】为啥 AWS Lambda 函数在回调函数执行之前完成?【英文标题】:Why Does AWS Lambda function finishes before callback function is executed?为什么 AWS Lambda 函数在回调函数执行之前完成? 【发布时间】:2018-08-12 16:13:27 【问题描述】:我正在开展一个项目,以从音频文件中获取脚本。音频文件的格式为 flac。我正在使用 AWS Lambda 并在 node.js 中编写了代码。此外,我正在使用 IBM Speech to text 服务并使用他们提供的基本示例代码,可以在 here 找到。问题是我的 lambda 函数在运行这些函数之前完成。
我正在从 s3 下载文件并将其存储在本地(工作正常)。之后,我试图将相同的文件传递给 IBM Speech to Text SDK,它应该将音频文件的脚本返回到本地存储
代码如下:
const downloadFile = function (url1, dest, cb)
const file = fs.createWriteStream(dest);
https.get(url1, function (res)
//res.setEncoding('binary');
res.pipe(file);
file.on('finish', function ()
const stats = fs.statSync(dest);
const fileSizeInBytes = stats.size;
//Convert the file size to megabytes (optional)
const fileSizeInMegabytes = fileSizeInBytes / 1000000.0;
console.log(fileSizeInMegabytes);
file.close();
RunIBMWatson(dest);
callback(null,"Nice");
);
);
;
function RunIBMWatson(dest)
console.log(dest);
console.log("I am here");
const recognizeStream = speech_to_text.createRecognizeStream(params);
fs.createReadStream(dest).pipe(recognizeStream);
recognizeStream.pipe(fs.createWriteStream('/tmp/transcription.txt'));
recognizeStream.setEncoding('utf8');
recognizeStream.on('results', function(event) onEvent('Results:', event); );
recognizeStream.on('data', function(event) onEvent('Data:', event); );
recognizeStream.on('error', function(event) onEvent('Error:', event); );
recognizeStream.on('close', function(event) onEvent('Close:', event); );
recognizeStream.on('speaker_labels', function(event) onEvent('Speaker_Labels:', event); );
function onEvent(name, event)
console.log("I am in onEvent");
if (name === 'data')
console.log(event);
这是我从 AWS Lambda 获得的函数日志:
2018-03-05 03:31:53.585 54.093469
2018-03-05 03:31:53.588 /tmp/sample.flac
2018-03-05 03:31:53.588 I am here
我是 AWS Lambda 和 Node.js 的初学者。所以如果有人能指出我犯的错误。
【问题讨论】:
【参考方案1】:是的,RunIBMWatson
是一个异步函数,因为文件 IO,所以因为你没有等待该函数的结果返回 - 回调被执行,从而结束你的 lambda 的执行。
将RunIBMWatson
的逻辑包装在 Promise 中,一旦获得所有数据并将其写入该脚本文件 - 解析函数。 MDN: Promises
const downloadFile = function (url1, dest, cb)
...
console.log(fileSizeInMegabytes);
file.close();
return RunIBMWatson(dest)
.then(() => // return data from promise resolve can be back and accessible as params
callback(null,"Nice");
function RunIBMWatson(dest)
return new Promise((resolve, reject) =>
const rStream = speech_to_text.createRecognizeStream(params);
fs.createReadStream(dest).pipe(rStream);
rStream.pipe(fs.createWriteStream('/tmp/transcription.txt'));
rStream.setEncoding('utf8');
rStream.on('results', function(event) onEvent('Results:', event); );
rStream.on('data', function(event) onEvent('Data:', event); );
rStream.on('error', function(event) onEvent('Error:', event); );
rStream.on('close', function(event) onEvent('Close:', event); );
rStream.on('speaker_labels', function(event) onEvent('Speaker_Labels:', event); );
function onEvent(name, event)
console.log("I am in onEvent");
if (name === 'data') // the data
resolve(); // you can return data too here
)
希望对你有帮助
【讨论】:
【参考方案2】:问题是 javascript 事件循环是空的,所以 Lambda 认为它已经完成。你可以下载一个 npm 模块async/await
来帮助解决这个问题。 info here
默认情况下不包含asyncawait,但这并不意味着您不能自己添加它。只需在本地添加包(npm install asyncawait),然后在上传 Lambda 函数之前将 node_modules 文件夹包含在 ZIP 中。
如果您想单独处理开发依赖项(例如:测试、aws-sdk 以在本地执行您的函数等),您可以将它们添加到 package.json 中的 devDependencies 下。
【讨论】:
谢谢。这有帮助。将开始使用 async/await以上是关于为啥 AWS Lambda 函数在回调函数执行之前完成?的主要内容,如果未能解决你的问题,请参考以下文章