1

I've created a very short/simple example of a problem I'm having with Promises in a script utilizing the aws-sdk package for Node.js.

In short, the script is not waiting at the await keyword. It loops through the loop without waiting for the async function to successfully complete before moving on.

Code example:


main.js

const AWS = require('aws-sdk')
import constants from '@/constants'

AWS.config.update({
  accessKeyId: constants.awsAccessKey,
  secretAccessKey: constants.awsSecretAccessKey,
  region: constants.awsRegion
})

export const s3 = new AWS.S3({apiVersion: '2006-03-01'})

click some button and trigger testS3() method...


testActions.js

import { s3 } from '@/main.js'

export async function testS3 () {
  const testParams = {
    Bucket: AWS_BUCKET,
    Key: `test_file.txt`,
    Body: 'Testing stuff'
  }

  async function testFunction(layer) {
    console.log('in prepare design 1')
    const result = await s3.putObject(testParams).promise()
    console.log(`the results: ${result}`)
  }

  [1,2,3].forEach(async (x) => {
    const result = await testFunction()
  })
}

Output from the debugger:

enter image description here


I was expecting the messages to be interleaved, which is what makes sense if you follow the flow of the logic.

It should be in prepare design 1, and then display the results..., then go through and do that 2 more times.

The output displaying in prepare design 1 three times right off the bat shows me that the loop is not waiting for the function before continuing.


Have I setup async/await wrong in some way? I've tried multiple different iterations and can't seem to get this working how I'm expecting it to.

2 Answers 2

4

The displayed behavior is correct, because forEach's handler is also an async function:

  async (x) => {
    const result = await testFunction()
  }

So the forEach loop will run 3 async functions immediately. Each of those function will await for the rest of the promise chain asynchronously.

If you want a synchronous execution, use a normal for loop:

for(var i=0; i<3; i++){
  const result = await testFunction()
}
Sign up to request clarification or add additional context in comments.

Comments

3

This an addition to AVAVT's answer (as I can't comment on it), you can also do so as such so you don't have to manually enter in the number of iterations and intending on using the iterating value.

import { s3 } from '@/main.js'

export async function testS3 () {
  const testParams = {
    Bucket: AWS_BUCKET,
    Key: `test_file.txt`,
    Body: 'Testing stuff'
  }

  async function testFunction(layer) {
    console.log('in prepare design 1')
    const result = await s3.putObject(testParams).promise()
    console.log(`the results: ${result}`)
  }

  for (const iterator of [1,2,3]) {
      const result = await testFunction();
  }

}

1 Comment

promise() at last is the solution. Thank you so much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.