node.js - Multiple Dynamo DB calls from Lambda Node JS

I need to loop through a json and make multiple getitem calls to dynamo db. My issue is that node js flies through the code not waiting for the function return so I can't create an xml that has a header, multiple calculated lines, and then a footer.

In the sample below, the !make footer would be written long before the function taxrate finishes. How can I force the script to wait for the taxrate function to finish?

!make xml header 
 for(i=0; i<linelength; i++)
    {

        business_unit = '100'
        invoice_line = 1
        total = 100
        taxrate(business_unit, invoice_line, total);       
        !write line xml
    }
!make xml footer

function taxrate(business_unit, i, gross_total) {

        const params = {
            Key: {
                "tax_rate": {
                    S: business_unit
                }
            },
            TableName:"tax_table"
        };
        dynamodb.getItem(params,function(err, data){
            if(err) {
                console.log("call error");
                console.log(err);

            } else {
               console.log(data.Item.tax.N);
               return(data.Item.tax.N);
            }
        });

1 Answer

  1. Jimmy- Reply

    2019-11-13

    There are several patterns for solving this problem; the first one is one you've already got in your code, which is the callback function. The function you are passing to dynamodb.GetItem() is a callback that executes after some other code is run, so that the result (data) can be accessed.

    A more modern way is to use Promises, which take a bit of time to understand. It's worth doing this though, so that you can understand what's happening behind the scenes when you use the newest way, which is async and await, which would look like this:

    exports.lambdaHandler = async (event, context) => {
        !make xml header 
        for(i=0; i<linelength; i++)
            {
    
                business_unit = '100'
                invoice_line = 1
                total = 100
                await taxrate(business_unit, invoice_line, total);       
                !write line xml
            }
        !make xml footer   
    }
    
    async function taxrate(business_unit, i, gross_total) {
        const params = {
            Key: {
                "tax_rate": {
                    S: business_unit
                }
            },
            TableName:"tax_table"
        };
        try {
            let data = await dynamodb.getItem(params).promise();
            return data.Item.tax.N;
        } catch(err) {
            console.log("call error");
            console.log(err);
        }
    }
    

    Notice that both lambdaHandler() and taxrate() have been turned into async functions. In the for loop, we've now awaited the result of taxrate(). The callback to getItem has been replaced with a method that returns a promise.

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>