javascriptpromiseasync-awaitamazon-sagemakermechanicalturk

Await returns too soon


I am retrieving a list of image filenames from DynamoDB and using those image filenames to replace the default src= image in a portion of a website.

I'm a JS novice, so I'm certainly missing something, but my function is returning the list of filenames too late.

My inline script is:

<script>
        customElements.whenDefined( 'crowd-bounding-box' ).then( () => {  
        var imgBox = document.getElementById('annotator');
        newImg = imageslist();
        console.log("Result of newImg is: " + newImg);
        imgBox.src = "https://my-images-bucket.s3.amazonaws.com/" + newImg;
    } )
</script>

My JS function is:

async function imageslist() {
    const username = "sampleuser";
    const params = {
        TableName: "mytable",
        FilterExpression: "attribute_not_exists(" + username + ")",
        ReturnConsumedCapacity: "NONE"
    };
    try {
        var data = await ddb.scan(params).promise()
        var imglist = [];
        for(let i = 0; i < data.Items.length; i++) {
            imglist.push(data.Items[i].img.S);
        };
        imglist.sort();
        var firstimg = imglist[0];
        console.log(firstimg);
        return imglist
    } catch(error) {
        console.error(error);
    }
}

The console reports Result of newImg is: [object Promise] and shortly after that, it reports the expected filename. After the page has been rendered, I can input newImg in the console and I receive the expected result.

Am I using the await syntax improperly?

Side note: This site uses the Crowd HTML Elements (for Ground Truth and Mechanical Turk), so I'm forced to have the src= attribute present in my crowd-bounding-box tag and it must be a non-zero value. I'm loading a default image and replacing it with another image.


Solution

  • Anytime you use the await keyword, you must use the async keyword before the function definition (which you have done). The thing is, any time an async function is called, it will always return a Promise object since it expects that some asynchronous task will take place within the function.

    Therefore,you'll need to await the result of the imageslist function and make the surrounding function async.

    <script>
        customElements.whenDefined( 'crowd-bounding-box' ).then( async () => {  
            var imgBox = document.getElementById('annotator');
            newImg = await imageslist();
            console.log("Result of newImg is: " + newImg);
            imgBox.src = "https://my-images-bucket.s3.amazonaws.com/" + newImg;
        } )
    </script>