javascript - 将项目从异步函数追加到数组

标签 javascript arrays node.js

我在将项目附加到数组时遇到问题,希望在执行此类操作时获得帮助。我已经评论过this并且理解为零。

这是我当前在 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 之后正确调用,而不是在调用 dynamoDb.scan 之后调用。鳍状。

所以你的代码中发生的是这样的:

  1. 您创建数组 sesData
  2. 您调用 dynamoDB.scan 并向其传递 onScan 回调函数。
  3. 该函数启动,但它是异步的,并且连接到 dynamoDB 等需要时间
  4. 您调用generateParams,但onScan函数尚未完成。

Your code generated the email before the onScan function added items to sesData.

要解决此问题,您需要:

  1. 在 onScan 回调中包含generateParams。
  2. 将 Promise 链与 .then 一起使用
  3. 使用异步/等待

我没有使用过 AWS,但快速谷歌搜索显示 scan 可以通过执行操作返回 promise

dyanmoDb.scan(params).promise()

请注意,这里没有回调函数,因为它返回一个 promise 。

然后你可以做类似的事情

exports.handler = async function(event, context) {
    ...
    await dynamoDb.scan(params).promise()
    ...
    console.log(sesData)
}

关于javascript - 将项目从异步函数追加到数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57227920/

相关文章:

javascript - 查看一个数组有多少个值相同

c - 如何在 C 中外部 SDL_Surface 数组?

c# - System.Array不包含添加的定义

javascript - 使用nodejs从MariaDB获取数据并将其发送到html页面(Express JS)

windows - 在 Windows 上运行 grunt.cmd 的多个问题

node.js - 如何使用 jwilder/nginx-proxy 设置反向代理?

javascript - Websocket 在刷新时不连接

java - MapReduce 返回 NaN

javascript - 使用 btn 对表单进行 HTML5 验证,触发 JS 函数发送 php 邮件并在成功时显示模式

javascript - 当我使用 <a> 标签跟随路线时,React-Router 正在刷新页面