Search code examples
node.jspromiseaws-sdk-nodejs

Returning promise values with `then`


In the below code snippet I am using then to get the result of a promise. However, response is not returned. What is returned is Promise { <pending> }.

I've logged response and can see it correctly returned the data, not a pending promise. So why is it returning a pending promise? I've even added a then call to the call to describeTable, and it still comes back pending.

I've read the following questions and they were not helpful, so please do not mark as a duplicate of them:

How do I return the response from an asynchronous call?

async/await implicitly returns promise?

const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-2'});
const docClient = new AWS.DynamoDB;

async function describeTable() {
    const params = {
        TableName: 'weatherstation_test',
    };

    let response;
    try {
        response = await docClient.describeTable(params).promise().then(result => result);
        console.log(response); // Logs the response data
    } catch (e) {
        console.error(e)
        throw e;
    }
    return response;
}

console.log(describeTable().then(result => result)); // Logs Promise { <pending> }

Update

So I've removed the first then (after promise()) because it is redundant. The answer from @libik works for me. It was the context in which then is run I wasn't understanding.


Solution

  • You cannot access the asynchronous content from synchronous one.

    If you want to log it, you have to do it from inside like this

    describeTable().then(result => console.log(result))

    In your case you are logging the output of asynchronous function, which is always a promise.


    What really happens: In Node.js all the synchronous content is executed first and any asynchronous content is put to event loop to be executed later.

    So first this is executed

    const AWS = require('aws-sdk');
    AWS.config.update({region: 'eu-west-2'});
    const docClient = new AWS.DynamoDB;
    console.log(describeTable()
    

    The function is called, so then it goes inside function. Because it is asynchronous function, it will execute it synchronously till the first await.

    const params = {
            TableName: 'weatherstation_test',
        };
    
        let response;
        try {
            response = await docClient.describeTable(params).promise()
    

    Now this promise is added to Event Loop to be executed later and the function describeTable() returns to the synchronous context (the console log) the promise, that will be linked through all your function asynchronously later and you log this promise (which is indeed pending).

    And now your synchronous context ends. Before the above promise is resolved your app can meanwhile executing other parts (which is always the same, take event from event loop, do the full synchronous part - which can push another events to event loop and then take another event and repeat)