Reputation: 2885
I have a chatbot that is storing information to Azure Tables. In one use case, I need to check and see if an entity exists, and if so, append an email address to a field in the entity and update it. I am using the azure-storage package. When I first started testing it was working, but after a few iterations it started skipping the function. I had been using the debugger and witnessed it going through the if (!err)
portion of the function. However, without changing (to my knowledge) any of the code, it is now skipping the entire function. I put additional breakpoints at the if and else statements as well as at the very end of the function, but it just bypasses everything and goes straight to the next block of code. That next block replaces the entity, and it is actually working fine. Only retrieveEntity is not working. I can't come up with any idea why this wouldn't be working. Any ideas? Functionally I can't see any reason why it wouldn't get into the function block at all, and I'm further perplexed that it was working at one point. Here is the block of code for both retrieveEntity and insertOrReplaceEntity.
tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
if (!err) {
if (!result.userEmail._.includes(conversationData.userEmail)) {
notifyEmail = `${result.userEmail._}, ${conversationData.userEmail}`;
} else {
notifyEmail = result.userEmail._;
}
} else {
notifyEmail = conversationData.userEmail;
}
});
<<some code to define lineData for entity>>
tableSvc.insertOrReplaceEntity('orderData',lineData, async function (err, result, response) {
if (!err) {
await step.context.sendActivity('OK, I will let you know once this line item ships.');
this.appInsightsClient.trackTrace({message: `Table API - ${path.basename(__filename)}`,severity: 1,properties: {request:lineData, response:response} });
} else {
console.log(err);
await step.context.sendActivity(`I wasn't able to set up that notification for you. Please try your search again later, and if your line still hasn't shipped I can try to set it up again.`);
this.appInsightsClient.trackTrace({message: `${err.name}/${err.code} - ${path.basename(__filename)}`,severity: 4,properties: {'request':lineData, 'error':err.message} });
}
});
Upvotes: 0
Views: 209
Reputation: 2885
Building on what @Gaurav Mantri posted I was able to come to an answer. I needed to use async/await in order to handle the botframework activities, and in addition that allowed me to only wrap the retrieveEntity function and not wrap the rest of the code. Here is how I solved it.
async function retrieveEntity() {
return new Promise((resolve) => {
tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
if (!err) {
console.log(result.userEmail._, conversationData.userEmail);
if (!result.userEmail._.includes(conversationData.userEmail)) {
notifyEmail = `${result.userEmail._},${conversationData.userEmail}`;
} else {
notifyEmail = result.userEmail._;
}
resolve(notifyEmail);
} else {
notifyEmail = conversationData.userEmail;
resolve(notifyEmail);
}
});
});
}
await retrieveEntity();
The key (probably obvious to most veteran coders) was that I had to return a promise. Otherwise it was just awaiting my call of the tableSvc and thus I was right back where I started. Setting it up in this way, the call to retrieveEntity awaits the resolution resolve(notifyEmail)
, and then with that value available, the rest of my function works as required.
Upvotes: 2
Reputation: 136336
Considering tableSvc.retrieveEntity
is an async operation (as it makes a network call and waits for the response to come), it's better to await the result of it. I agree with you that waiting for a predetermined interval (1.5 seconds in your case) is not an optimal solution.
One possible solution is to wrap the call to retrieve entity in a function that returns a Promise
so that you wait for that promise to get fulfilled.
Here's the pseudo code I came up with (not tested):
function retrieveEntity() {
return new Promise((resolve) => {
tableSvc.retrieveEntity('orderData', 'Vista', lineKey, function(err, result, response) {
if (!err) {
if (!result.userEmail._.includes(conversationData.userEmail)) {
notifyEmail = `${result.userEmail._}, ${conversationData.userEmail}`;
} else {
notifyEmail = result.userEmail._;
}
resolve(notifyEmail);
} else {
notifyEmail = conversationData.userEmail;
resolve(notifyEmail);
}
});
});
}
retrieveEntity
.then((result) => {
//some code to define lineData for entity
//
//
tableSvc.insertOrReplaceEntity('orderData',lineData, async function (err, result, response) {
if (!err) {
await step.context.sendActivity('OK, I will let you know once this line item ships.');
this.appInsightsClient.trackTrace({message: `Table API - ${path.basename(__filename)}`,severity: 1,properties: {request:lineData, response:response} });
} else {
console.log(err);
await step.context.sendActivity(`I wasn't able to set up that notification for you. Please try your search again later, and if your line still hasn't shipped I can try to set it up again.`);
this.appInsightsClient.trackTrace({message: `${err.name}/${err.code} - ${path.basename(__filename)}`,severity: 4,properties: {'request':lineData, 'error':err.message} });
}
});
});
Upvotes: 1