I’m trying to call a rest service from within a component handler. Unfortunately when I use async/await all speech output in my Alexa skill is lost. I used the request example from v3.
How to make async calls in v4 Component handler?
How long is the wait?
I’m doing this in the current version of my new-sounds-on-demand skill, and as long as the REST routine returns quickly I’m fine. When it was taking an unreasonably long time (due to a bug in my code), the Alexa interaction timed out before I could respond.
The complete call takes about 300ms and about 1KByte of data is transported.
Actually everything looks normal.
I also tried it with another lightweight REST call with the same result.
Maybe there’s more to it than a simple async/await within a handler.
What happens if you dummy out that call? That would establish clearly whether the async/wait is actually the relevant factor.
Hello there,
Here’s an example how an async call inside a component handler could look like:
import { BaseComponent, Component } from '@jovotech/framework';
@Component()
export class ExampleComponent extends BaseComponent {
async someHandler() {
await this.$send('Hello world! This is an async call.');
}
}
I hope this helps.
async handleMyData(){
const res = await axios.get('http://localhost:8080/rest/items?recursive=false', {
headers: {
Accept: 'application/json'
},
}).then(response => {
return response.data;
}).catch(err => {
console.log(err);
});
return this.$send({message:'Data returned',listen: false});
}
The result is the same for request and axios lib, no alexa response.
Could you try this?
async handleMyData(){
const res = await axios.get('http://localhost:8080/rest/items?recursive=false', {
headers: {
Accept: 'application/json'
},
});
return this.$send({message:'Data returned',listen: false});
}
It would also be good to see how you’re calling the handleMyData
handler. From a different handler or is it entered with an intent?
I tried your code, but unfortunately it doesn’t work either.
Here’s how I call the handler:
START() {
return this.$redirect(TemperatureComponent, 'handleMyData');
}
I added the redirect to test with different handler implementations.
Here some results of my async/await tests:
If I implement everything in the GlobalComponent, then it works fine.
However, when I redirect to another component via $redirect method and call a handler that uses async/await I get an incorrect response.
Attached the incorrect response for redirect:
{
"body": {
"version": "1.0",
"response": {
``"shouldEndSession": false,
"type": "_DEFAULT_RESPONSE"
},
"sessionAttributes": {
"createdAt": "2021-12-17T17:22:13.564Z",
}, "data": {},
"id": "amzn1.echo-api.session.8f33d48f-3508-417a-95bb-2bb1fd0f0d9f",
"state": [
{
"component": "TemperatureComponent"
}
],
}, "isNew": true,
"updatedAt": "2021-12-17T17:22:13.564Z"
}
}
}
In the response above outspeech part is missing and I get type “_DEFAULT_RESPONSE” and property ‘shouldEndSession’ is false instead of true.
All testing was done for the Alexa platform only.
Hey @wkl
Could you share your code in handleMyData
?
I tried to reproduce it with a dummy API call.
// AsyncComponent.ts
@Component()
export class AsyncComponent extends BaseComponent {
async handleMyData() {
const result = await apiCall();
return this.$send( { message: 'Result is: ' + result });
}
}
function apiCall() {
return new Promise((resolve) => {
setTimeout(() => {
return resolve('okay');
}, 1000);
})
}
// GlobalComponent.ts
@Global()
@Component()
export class GlobalComponent extends BaseComponent {
LAUNCH() {
return this.$redirect(AsyncComponent, 'handleMyData');
}
}
It works as expected.
For a description of handleMyData() please see my previous post.
I moved all my code to the GlobalComponent where it works just fine.
Not sure what the problem was with the redirect.