全局变量未在函数内部更新

时间:2020-02-10 18:01:30

标签: javascript node.js

给出以下代码

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)

由于某种原因,我的变量base64不显示任何内容。这很奇怪,因为当我执行console.log(data.Item.b.toString('base64')时,它会打印base64字符串,因此我确定数据肯定不是空的。

由于某些原因,我的变量没有更新,我不确定为什么。我显然是在调用函数fetchOneByKey(),因此从理论上说base64应该得到更新,但不是。

1 个答案:

答案 0 :(得分:2)

docClient.get()是异步的。通过在调用该函数之后立即调用console.log(),就可以在从数据库读取完成之前执行它,因此不会更新您的变量。

在此处致电console.log(base64)

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

如果要摆脱回调并改为使用Promise,则可以使用promisify。这样,您就可以将其变成一个承诺,并与async/await一起使用,或与.then()链接。

或者您也可以手动实现它。

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)
      }
    })
  }
}

然后您可以说base64 = await fetchOneByKey(); 或者如果您不在async函数内部,则可以执行fetchOneByKey().then(base64 => console.log(base64))

编辑: 正如@AZ_所提到的,aws-sdk支持诺言

let fetchOneByKey = async function () {
  var params = {
    ...
  }
  const data = await docClient.get(params).promise();
  base64 = data.Item.b.toString('base64');
  return base64
}