javascript - 从异步函数将项目附加到数组
问题描述
我在将项目附加到数组时遇到问题,希望在执行此类操作时得到帮助。我已经对此进行了审查并理解为零。
这是我当前在 AWS Lambda (Node.js 10.x) 中运行的代码:
var sesData = ["array0", "array1"];
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Scan succeeded.");
data.Items.forEach(function(itemdata) {
// append new value to the sesData array
sesData.push("Item :" + JSON.stringify(itemdata));
console.log(sesData);
console.log("Item :",JSON.stringify(itemdata));
});
// continue scanning if we have more items in case it is lots of data
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
params2.ExclusiveStartKey = data.LastEvaluatedKey;
dynamoDB.scan(params2, onScan);
}
}
}
function generateEmailParams (body) {
return {
Source: myEmail,
Destination: { ToAddresses: [myEmail] },
ReplyToAddresses: [myEmail],
Message: {
Body: {
Text: {
Charset: 'UTF-8',
Data: `Message sent. \nContent: \n${sesData}`
}
},
Subject: {
Charset: 'UTF-8',
Data: `Subject`
}
}
}
}
//End email Params
exports.handler = function(event, context) {
console.log("Incoming: ", event);
dynamoDB.scan(params2, onScan); // scanning DDB
console.log('===SENDING EMAIL===');
const emailParams = generateEmailParams(event.body)
var email = ses.sendEmail(emailParams, function(err, data){
if(err) console.log(err);
else {
console.log("===EMAIL SENT===");
console.log(data); // log data
console.log("EMAIL CODE END"); //log end of email
console.log('EMAIL: ', email); // log email
context.succeed(event);
}
});
};
所有 ses 项目只是通过电子邮件发送 onScan 函数数据。这很好用,不是麻烦,它是 sesData 永远不会附加的。console.log 打印出 dynamoDB 中的数据没有问题,但推送到数组不起作用。
在互联网上搜索后,我真的不明白发生了什么,因为没有错误,所以我错过了某种逻辑。
解决方案
异步意味着代码的执行顺序与您编写它的顺序不同。
dynamoDB.Scan 是一个异步函数。您正在与您的 DynamoDB 交谈,这需要时间,可能只有几毫秒,但 NodeJS 将在完成扫描功能时继续执行下一行代码。
让我们看下面的例子
let count = 1
console.log(count)
setTimeout(function() {
count = 2
console.log(count)
}, 1000)
count = 3
console.log(count)
setTimeout 是一个异步函数,它在 x 毫秒后执行,在本例中为 1000 毫秒 = 1 秒。所以它类似于您的 dynamoDB.scan 函数,它会立即启动,但需要一些时间才能完成,同时,nodeJS 将继续逐行运行您的代码。
所以代码的顺序是 1、2、3。但是当你运行代码片段时,它会出现 1、3、2。即使您将超时设置为 0 毫秒,它仍然是 1,3,2
let count = 1
console.log(count)
setTimeout(function() {
count = 2
console.log(count)
}, 0)
count = 3
console.log(count)
这是因为它是一个异步函数,将被放在调用堆栈的底部。Callstack 是一个花哨的 JavaScript 词。
要了解此结帐:https ://www.youtube.com/watch?v=8aGhZQkoFbQ 这是一个非常好的视频,它解释了 JavaScript 如何工作并且不难理解。
请注意,onScan 函数是一个回调函数,并在 dynamoDb.scan 方法完成时执行。所以它就像“嘿 DynamoDB,调用扫描函数,然后执行我创建的 onScan 东西”
您对它进行了编程,以便在 DynamoDB.scan 完成后调用 onScan,这会添加到 sesData 数组中,但 generateParams 函数位于回调之外,因此在您调用 dynamoDb.scan 后会立即调用它,而不是在它完成后调用。
所以你的代码中发生的是这样的:
- 您创建数组 sesData
- 您调用 dynamoDB.scan 并将其传递给 onScan 回调函数。
- 该函数启动,但它是异步的,连接到 dynamoDB 等需要时间
- 您调用 generateParams,但 onScan 函数尚未完成。
您的代码在 onScan 函数将项目添加到 sesData 之前生成了电子邮件。
要解决此问题,您需要:
- 在 onScan 回调中包含 generateParams。
- 使用带有 .then 的承诺链
- 使用异步/等待
我没有使用过 AWS,但快速谷歌搜索显示扫描可以通过执行返回承诺
dyanmoDb.scan(params).promise()
注意这里没有回调函数,因为它返回一个promise。
然后你可以做类似的事情
exports.handler = async function(event, context) {
...
await dynamoDb.scan(params).promise()
...
console.log(sesData)
}
推荐阅读
- python - 如何在使用tensorlflow时计算数组的分量
- mongodb - mongo db聚合键
- php - WooCommerce 存档页面上的自定义数量字段功能问题
- c++ - 模板生成器错误的显式复制构造函数
- cassandra - 可以针对现有表数据运行 cassandra-stress 工具吗?
- android - Flutter - 键盘隐藏时TextFormField变为空白
- symfony - 我在哪里可以找到 Symfony 项目的 CI 服务?
- mysql - AWS 中的子查询
- c# - Xamarin Forms ControlTemplate TapGestureRecognizer 命令绑定
- matlab - 自动响应提示内循环