为什么AWS Lambda函数在执行回调函数之前完成?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么AWS Lambda函数在执行回调函数之前完成?相关的知识,希望对你有一定的参考价值。

我正在研究一个项目,以便从音频文件中获取成绩单。音频文件的格式为flac。我正在使用AWS Lambda并在节点中编写代码。此外,我正在使用IBM Speech来提供文本服务,并使用他们提供的基本示例代码,可以找到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的入门者。所以,如果有人能指出我正在犯的错误。

答案

Yea RunIBMWatson是一个异步函数,因为文件IO,所以因为你没有等待该函数返回的结果 - 执行回调从而结束了lambda的执行。

RunIBMWatson的逻辑包含在Promise中,一旦获得所有数据并将其写入该transcript文件 - 解析该函数​​。 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
      }
    }
  })
}

希望这可以帮助

另一答案

问题是javascript事件循环是空的,所以Lambda认为它已经完成了。你可以下载一个npm模块async/await来帮助你。 info here

默认情况下不包含asyncawait,但这并不意味着您无法自行添加。只需在本地添加软件包(npm install asyncawait),并在上传Lambda函数之前在ZIP中包含node_modules文件夹。

如果你想单独处理dev依赖项(例如:test,aws-sdk以在本地执行你的函数等),你可以在package.json中的devDependencies下添加它们。

以上是关于为什么AWS Lambda函数在执行回调函数之前完成?的主要内容,如果未能解决你的问题,请参考以下文章

AWS Lambda 在向 SQS 发送消息之前完成

如何在AWS Lambda函数中进行外部api调用

使用 Node.js 从 AWS Lambda 函数连接到 MySql 数据库,没有连接回调

在 AWS lambda 上列出 cognito userpool 用户

AWS lambda函数未终止线程

什么是AWS Lambda?——事件驱动的函数执行环境