AWS Lambda和承诺:未调用回调

时间:2019-05-10 21:23:32

标签: javascript node.js promise async-await aws-lambda

我假设我在诺言方面缺乏一些基本知识。我有一个在AWS Lambda内的流程,该流程下载三个文件,然后生成通过电子邮件发送的输出。

module.exports.test = async (event) => {
   var p = download1();
   var c = download2();
   var h = download3();

   await Promise.all([p, c, h]).then(() => {
     ... bunch of logic manipulating the data
     customers.forEach(i => {
       buildFile().then(data => {
         sendEmail(data).then(response => {
            console.log('Email sent successfully');
         });
       });
     });
   }, errHandler);
};

buildFile和sendEmail函数均返回Promise,但我从未收到“成功发送电子邮件”消息。它运行代码,但实际上不会在Lambda完成之前返回(至少我认为这是正在发生的事情)。

我的理解是Promise将完成回调,但是现在我想我需要做的事情与在原始Promise.all()中进行下载的方式类似。那是正确的方向吗?

该过程应获取文件,然后循环遍历客户以创建每个文件并通过SES发送。

2 个答案:

答案 0 :(得分:6)

您正在寻找

module.exports.test = async (event) => {
  var p = download1();
  var c = download2();
  var h = download3();

  try {
    await Promise.all([p, c, h]);

    // ... bunch of logic manipulating the data
    var promises = customers.map(async (i) => {
      var data = await buildFile();
      var response = await sendEmail(data);
      console.log('Email sent successfully');
    });
    await Promise.all(promises);
  } catch(e) {
    errHandler(e);
  }
};

您的test函数没有等待您在forEach循环中创建的承诺,因此lambda在完成所有操作之前就完成了。

答案 1 :(得分:1)

@Bergi的答案是正确的,但是我想稍微扩展一下,并为您提供一些资源来增加或增强您的Promises知识。我将使用下一个代码段,这有点麻烦,因为我是在Google Chrome代码段上编写的,因此可以随时将其粘贴并使用它:

(function() {
    const promise1 = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve('Replicant');
        }, 300);
    });

    const promise2 = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve('Human?');
        }, 300);
    });

    function buildFile(type) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(`${type}`);
            }, 300);
        });
    }

    function sendMail(customer, answer) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(`Sent test to: ${customer}, he/she is a ${answer}`);
            }, 300);
        });
    }

    let customers = ['Rob Batty', 'Rachel', 'Deckard'];

    async function myFunc() {

        const [a, b, c] = await Promise.all([promise1, promise1, promise2]);
        const answers = [a, b, c];

//         const promises = customers.map(async (name, index) => {
//             const file = await buildFile(answers[index]);
//             const mail = await sendMail(name, file);
//             console.log(mail);
//         });

        const promises = customers.map((name, index) => {
            buildFile(answers[index])
                .then(file => sendMail(name, file))
                .then(sent => console.log(sent))
                // If you're going to use Promises this is important! :D
                .catch(err => console.log(err))
        });

        const [m1, m2, m3] = await Promise.all(promises);

        console.log(m1, m2, m3);
    }

    myFunc();
})()

正如答案中指出的那样,问题与forEach的使用有关,为什么?好吧,仅因为您是在asynchronous类型的方法上执行synchronous代码,所以相处的不是很好:),因此,解决方案是创建一个Array的方法Promises,就像Factory。在map函数之后,PromisesPending也不是FullfiledRejected,这是在您调用Promise.all()方法时等待它们的结果以及他们为您提供值或在您的用例中,生成文件,然后将电子邮件发送给用户。希望这有助于您更好地了解Promises的工作方式。最后,我将留下两个非常重要的链接,至少对我而言,这在一定程度上帮助了Promises。干杯,辛辣的。