0

Given the following Code

var base64 = ''
const AWS = require('aws-sdk')
let awsConfig = {
  'region': 'us-west-2',
  'endpoint': 'http://dynamodb.us-west-2.amazonaws.com',
  'accessKeyId': 'ABCDEFGHIJKLMANOPQRSTUVWXYZ',
  'secretAccessKey': 'ABCDABSDJFGJALGJADSLGJALKDJGALKSDJGLA'
}

AWS.config.update(awsConfig)

let docClient = new AWS.DynamoDB.DocumentClient()

let fetchOneByKey = function () {
  var params = {
    TableName: 'test',
    Key: {
      'key1': 'abc'
    }
  }
  docClient.get(params, function (err, data) {
    if (err) {
      console.log('test::fetchOneByKey::error - ' + err)
    } else {
      base64 = data.Item.b.toString('base64')
    }
  })
}

fetchOneByKey()
console.log(base64)

For some reason my variable base64 prints nothing. This is weird because when I do console.log(data.Item.b.toString('base64') it prints the base64 string so i know the data is not empty for sure.

For some reason my variable is not getting updated and I am not sure why. I am clearly calling the function fetchOneByKey() so in theory base64 should get updated but it is not.

Dinero
  • 1,070
  • 2
  • 19
  • 44

1 Answers1

2

docClient.get() is asynchronous. By calling console.log() immediately after calling the function, you are executing it before the read from DB is finished, and thus your variable isn't updated.

Call console.log(base64) here

else {
  base64 = data.Item.b.toString('base64')
  console.log(base64)
}

If you want to get rid of the callback and use promises instead, you can use promisify. With that you can turn it into a promise and use it with async/await or chain it with .then().

Or you can make it as promise manually.

let fetchOneByKey = function () {
  var params = {
    TableName: 'test',
    Key: {
      'key1': 'abc'
    }
  }
  return new Promise((resolve, reject) => {
    docClient.get(params, function (err, data) {
      if (err) {
        console.log('test::fetchOneByKey::error - ' + err)
        reject(err)
      } else {
        base64 = data.Item.b.toString('base64')
        resolve(base64)
      }
    })
  }
}

then you can say base64 = await fetchOneByKey(); or if you are not inside an async function you can do fetchOneByKey().then(base64 => console.log(base64))

EDIT: as @AZ_ mentioned, aws-sdksupports promises

let fetchOneByKey = async function () {
  var params = {
    ...
  }
  const data = await docClient.get(params).promise();
  base64 = data.Item.b.toString('base64');
  return base64
}
Mirakurun
  • 4,859
  • 5
  • 16
  • 32