Reputation: 83
I'm having problems with dynamoDB not giving me the result of a query within a for loop. The query does execute, but it only executes after the loop has completed:
readMatchData(JSON) {
return new Promise((resolve, reject) => {
for (var jsonInfo of JSON.Feed.MatchData) {
var matchID = jsonInfo['@attributes'].matchID;
console.log("matchID: " + matchID);
var homeTeamID = team['@attributes'].homeTeamID;
var params = {
TableName: "Teams",
KeyConditionExpression: "#teamID = :teamID",
ExpressionAttributeNames: {
"#teamID": "teamID"
},
ExpressionAttributeValues: {
":teamID": homeTeamID
},
ReturnConsumedCapacity: "TOTAL"
}
docClient.query(params, function(err, data) {
if (err) {
//console.log("We have an error when looking for the team in the Teams table");
console.log(err);
} else {
if (data.Count === 0) {
//We did not find this ID in the db so we can add it.
console.log("The team doesn't exist");
} else {
data.Items.forEach(function(item) {
console.log("Team " + item.teamID + " " + item.teamName + " found in the database");
})
}
}
});
}
resolve("done");
});
}
In the console this returns me:
matchID: 3434
matchID: 3543
Team 3388 Hill U23 Team found in the database
Team 44108 Bridge U23 found in the database
Rather than:
matchID: 3434
Team 3388 Hill U23 Team found in the database
matchID: 3543
Team 44108 Bridge U23 found in the database
Upvotes: 2
Views: 1783
Reputation: 312
The issue is that the docClient
call uses a callback as seen in this line:
docClient.query(params, function(err, data) { ... })
This means that the function you're passing is not called until the operation is complete, which can be some time later.
You can tell the library to wrap it in a promise and then await it:
const data = await docClient.query(params).promise()
if (data.Count === 0) {
//We did not find this ID in the db so we can add it.
console.log('The team doesn\'t exist')
} else {
data.Items.forEach(function (item) {
console.log('Team ' + item.teamID + ' ' + item.teamName + ' found in the database')
})
}
Edit: Currently you're wrapping your whole function in a promise, but since we're isolating that to just the callback, you probably want to replace that to look something more like:
async function readMatchData () {
for (var jsonInfo of JSON.Feed.MatchData) {
var matchID = jsonInfo['@attributes'].matchID
console.log('matchID: ' + matchID)
var homeTeamID = team['@attributes'].homeTeamID
var params = {
TableName: 'Teams',
KeyConditionExpression: '#teamID = :teamID',
ExpressionAttributeNames: {
'#teamID': 'teamID'
},
ExpressionAttributeValues: {
':teamID': homeTeamID
},
ReturnConsumedCapacity: 'TOTAL'
}
const data = await docClient.query(params).promise()
if (data.Count === 0) {
//We did not find this ID in the db so we can add it.
console.log('The team doesn\'t exist')
} else {
data.Items.forEach(function (item) {
console.log('Team ' + item.teamID + ' ' + item.teamName + ' found in the database')
})
}
}
return 'done'
}
EDIT: Credit to HMilbradt for pointing out the library has a built in promisify function
Upvotes: 4