2

I am currently working on an Alexa Skill to collect data from an SAP system. Because of a callback in my function to collect the data, Alexa speaks, before the speakOutput variable gets updated.

const LagerhueteIntent = {
 canHandle(handlerInput) {
 return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
 Alexa.getIntentName(handlerInput.requestEnvelope) === 'LagerhueteIntent';
 },
 handle(handlerInput) {
 let speakOutput;
 console.log("test");
 findWarehouseKeepers(function(warehouseKeeper) {
 console.log(warehouseKeeper);
 speakOutput = "Die Lagerhüter sind die Produkte mit den Ids" + warehouseKeeper;
 console.log(speakOutput);
 });
 return handlerInput.responseBuilder
 .speak(speakOutput)
 //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
 .getResponse();
 }
};

With my function:

function findWarehouseKeepers(callback) {
 var args = getArgs();
 console.log(args);
 var Client = require('node-rest-client').Client;
 var client = new Client();
 client.get("http://XXXXXXXX$format=json", args, function(data, response) {
 let validValuesList = new List([]);
 data.d.results.forEach(function(data) {
 validValuesList.add(data.ProductId);
 });
 console.log(validValuesList);
 let validValuesAsArray = validValuesList.toArray();
 console.log(validValuesAsArray);
 callback(validValuesAsArray);
 });
}

How can I get my function synchronized, so the speakOutput variable gets updated before the next code gets executed? Thanks in advance.

asked Dec 17, 2020 at 15:03
3
  • Forget trying to return something from a function that only initializes an async operation. IMO do the .speak part inside the callback function that you provide to findWarehouseKeepers. Commented Dec 17, 2020 at 15:08
  • 1
    Can handle return a promise for the response? Commented Dec 17, 2020 at 15:08
  • 1
    @Bergi: Yes. I was just researching this. developer.amazon.com/en-US/docs/alexa/… Commented Dec 17, 2020 at 15:08

1 Answer 1

2

As per documentation, handle can return a promise, which will allow you to build the response once you received the data.

Ideally you would change findWarehouseKeepers to return a promise, but here is an example with minimal changes to your code:

handle(handlerInput) {
 return new Promise(resolve => {
 findWarehouseKeepers(warehouseKeeper => {
 const speakOutput = "Die Lagerhüter sind die Produkte mit den Ids" + warehouseKeeper;
 resolve(
 handlerInput.responseBuilder
 .speak(speakOutput)
 .getResponse()
 );
 });
 });
}

Of course you would also want to think about what to do if the request fails, i.e. you want to reject the promise.


If you change findWarehouseKeepers to return a promise then you could probably write declare handle as async (I don't know in which environment this code runs) and write the code in a way that looks synchronous:

async handle(handlerInput) {
 const warehouseKeeper = await findWarehouseKeepers();
 return handlerInput.responseBuilder
 .speak("Die Lagerhüter sind die Produkte mit den Ids" + warehouseKeeper)
 .getResponse()
}
answered Dec 17, 2020 at 15:12
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.