Javascript AWS Lambda函数不';t第一次发送消息,但后续每次都发送消息

Javascript AWS Lambda函数不';t第一次发送消息,但后续每次都发送消息,javascript,node.js,amazon-web-services,aws-lambda,amazon-sqs,Javascript,Node.js,Amazon Web Services,Aws Lambda,Amazon Sqs,我有一个lambda函数,它是通过API网关启动的(这是可行的) 然后lambda将一些数据添加到DynamoDB(这是可行的) 然后调用我创建的函数,该函数将数据发送到SQS export const AddToQueue = async vehicleId => { const QueueParams = { DelaySeconds: process.env.QUEUE_DELAY, MessageAttributes: {}, }; QueuePara

我有一个lambda函数,它是通过API网关启动的(这是可行的)

然后lambda将一些数据添加到DynamoDB(这是可行的)

然后调用我创建的函数,该函数将数据发送到SQS

export const AddToQueue = async vehicleId => {
  const QueueParams = {
    DelaySeconds: process.env.QUEUE_DELAY,
    MessageAttributes: {},
  };

  QueueParams.MessageAttributes.vehicleId = {
    DataType: 'String',
    StringValue: vehicleId,
  };

  QueueParams.QueueUrl = 'my-queue-url';
  QueueParams.MessageBody = `vehicle: ${vehicleId} - ${new Date().toISOString()}`;

  try {
    await sqs.sendMessage(QueueParams).promise();
    console.log(`SQS:SUCCESS - AddToQueue - ${vehicleId}`);
  } catch (error) {
    console.log(`SQS:ERROR - AddToQueue - ${error}`);
  }
};
第一次发生这种情况时,消息不会到达SQS,但任何其他后续消息都会添加到队列中并进行处理。我已经尝试了很多事情,包括IAM权限、队列设置、重新创建队列,但这些都没有帮助


我没有收到成功或错误消息,因此无法调试任何问题。

我不是这方面的专家,但我以前经历过这种行为,第一次调用中的某些异步代码似乎没有执行或执行延迟(例如,后续调用执行的操作似乎基于上一次调用的数据)


在所有情况下,这都是由于异步代码没有被正确地等待。我对javascript和Lambda都不太了解,无法解释其行为,尤其是延迟-承诺可以在处理程序返回后但容器仍在运行时解决吗?但我知道的是,如果Lambda在承诺之前返回(异步函数返回承诺)已解决(因此在异步代码完成运行之前,这会导致观察到的代码行为被延迟或未执行),则未正确等待它们。

可能您没有在调用的异步函数内等待
AddToQueue()

如果您没有在异步函数中调用并等待它,AddtoQueue()将在该代码执行后运行

让我给你举个例子

测试目录中有2个文件

wait.js main.js

wait.js是:

module.exports = async ()=> {

await new Promise((res, rej)=>{
    setTimeout(()=>{
        res(console.log('Running'));
    }, 2000)
})
}

还有main.js

console.log('Hello')
require('./await')();

console.log('World')
运行main.js时,
node main.js
Hello world
将运行,然后在承诺解决后,它将从队列推送到运行堆栈并运行最后一个

Hello
World
// After 2 secs
Running
但是如果在main.js中

(async ()=>{
console.log('Hello')
await require('./await')();

console.log('World')
})()
您让javascript引擎知道,这是一个异步函数,并在运行其他任何操作之前等待该模块,您将得到预期的结果

Hello
// After 2 seconds
Running
World

基本上,您是在告诉javascript引擎
我不想让您按自己的方式运行它,但按我的方式运行它

我刚才遇到了一个与此非常相似的问题,我的问题与未正确等待有关,正如公认答案中提到的@404

具体地说,我使用
forEach
遍历一个数组,并在回调中调用
await

//导致奇怪的行为
异步函数invokeLambdas(团队){
teams.forEach(异步(团队)=>{
wait utils.invokeLambda(team)//fn中有一个Lambda调用
});
我通过删除forEach的
forEach
并用一个常规for循环替换它,并按照建议在内部等待,从而解决了这个问题

异步函数调用lambdas(团队){
for(团队中的const团队){
等待utils.invokeLambda(团队)
}
}

当您第一次执行
AddToQueue
时,会打印哪个
console.log
?@PedroArantes没有触发任何一个,没有任何显示它的函数没有触发。请粘贴调用
AddToQueue()的代码
你有完整的Lambda代码吗?第一次调用和下一次调用之间的唯一区别是变量已经定义。我很确定问题在于没有正确地等待代码的某个异步部分,但我们只能猜测而看不到其余的代码。你发布的函数看起来很完美对我来说很好,但它的用法可能不是。我们有没有办法设置时间,或者让lambda等到所有等待调用完成?@MukulMunjal是的,只要正确地等待它们就行了。我对这个问题的经验是,当javascript代码中出现问题时,就会出现这种行为,通常是一些复杂的嵌套内容,其中一些是异步的功能没有得到适当的等待(或者换句话说,有些承诺没有得到解决).自从我发布这篇文章以来,我对js和lambda都有了更多的经验,我知道如何正确使用它们,我们从来没有遇到过这个问题。也就是说,lambda工作得很好,所以如果你遇到这种情况,你的js代码中就有bug。好的,当我在本地运行代码时,它工作得很好。第二,当我执行lambda函数时在2-3分钟内第二次运行两次,效果很好。对于mID的(const[k,v]){if(k.match(/^[0-9a-fA-F]{24}$/){const us=wait Model.findById(k);const u=wait Model.findOne({aId:us.\u id});if(!u){wait Model.create({aId:k,});}else{u.today=0;if(total>u.Limit){wait Model.findOneAndUpdate({u id:u.atId},{$set:{Limit:true}}});}wait u.save();}上面是我在lambda函数中使用的代码