通过异步函数将项目追加到数组

时间:2019-07-26 23:18:19

标签: 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打印出数据,但无法推送到阵列。

在Internet上进行搜索后,由于没有错误,我真的不知道发生了什么,因此我缺少某种逻辑。

1 个答案:

答案 0 :(得分:2)

异步意味着代码的顺序不会按照您编写代码的顺序执行。

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 ms之后执行,在这种情况下为1000 ms = 1 sec。因此,它与dynamoDB.scan函数类似,它立即启动,但是需要一些时间才能完成,同时,nodeJS将继续逐行运行代码。

因此,代码的顺序是1、2、3。但是运行代码段时,代码是1、3、2。即使您将超时设置为0 ms,它仍将是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之后会正确调用它,而不是在调用之后精打细算。

因此,您的代码中发生的事情是这样的:

  1. 您创建数组sesData
  2. 您调用dynamoDB.scan并将其传递给onScan回调函数。
  3. 该功能已启动,但它是异步的,需要花费一些时间才能连接到dynamoDB等。
  4. 您调用了generateParams,但是onScan函数尚未完成。
  

在onScan功能将项目添加到之前,您的代码已生成电子邮件   sesData。

要解决此问题,您需要:

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

我还没有使用过AWS,但是快速谷歌搜索表明扫描可以通过做来返回承诺

dyanmoDb.scan(params).promise()

请注意,此处没有回调函数,因为它返回了Promise。

然后您可以执行类似的操作

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