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

时间:2018-03-05 03:36:42

标签: node.js aws-lambda ibm-watson

我正在开发一个项目,以便从音频文件中获取成绩单。音频文件的格式为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的首发。所以,如果有人能够指出我正在犯的错误。

2 个答案:

答案 0 :(得分:1)

问题是javascript事件循环是空的,所以Lambda认为它已经完成了。您可以下载npm模块async/await,这将有助于此。 info here

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

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

答案 1 :(得分:1)

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

在承诺中包含RunIBMWatson的逻辑,一旦获得所有数据并将其写入该记录文件 - 解析该功能。 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
      }
    }
  })
}

希望这有帮助