This is not through any third-party code editor. This is through the Alexa Developer Console.
I am trying to create a skill for my school to get the current updates if the school is closed, two-hour delay, etc.
This is the code that handles it:
const GetCurrentUpdateHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'GetCurrentUpdate'
},
handle(handlerInput) {
let speakOutput = ""
axios.get("District Link")
.then(res => {
const dom = new JSDOM(res.data)
const msgs = dom.window.document.getElementById("onscreenalert-ctrl-msglist")
const useless = msgs.querySelectorAll("input")
useless.forEach(function (el) {
el.parentNode.removeChild(el)
})
const message = msgs.innerText
if (message === undefined) {
console.log("no messages")
speakOutput = "There are currently no messages."
finishReq(speakOutput)
} else {
console.log("message")
speakOutput = `Here is a message from District. ${msgs.innerText}`
finishReq(speakOutput)
}
})
function finishReq(output) {
return handlerInput.responseBuilder
.speak(output)
.getResponse();
}
}
}
I am getting a "SpeechletResponse was null" error.
Two things...
Because of the promise on axios.get, the function itself could be terminating and returning nothing before the promise is fulfilled.
Consider using async-await to pull the results of the axios.get call synchronously.
finishReq returns the response builder to the function that called it, not as the result of the handler. So even if you use async-await, wrapping the handler return in a function redirects it and doesn't return it to the SDK for transmission to Alexa.
So:
async handle(handlerInput)
const res = await axios.get(...)
Unwrap the .then and finishReq code so it's all in the handler scope.
For others who may find this post, your handler isn’t returning anything,; that's why you're getting the error.
You need:
return axios.get("District Link")
.then(res => {
and
return finishReq(speakOutput)
for the two places you call finishReq.
Related
I developed login function use by react-query in my react app
The logic is as follows
First restAPI for checking duplication Email
If response data is true, send Second restAPI for sign up.
In this case, I try this way
// to declare useMutation object
let loginQuery = useMutation(checkDuple,{
// after check duplication i'm going to sign up
onSuccess : (res) => {
if(res === false && warning.current !== null){
warning.current.innerText = "Sorry, This mail is duplicatied"
}else{
let res = await signUp()
}
}
})
//---------------------------------------------------------------------------------
const checkDuple = async() => {
let duple = await axios.post("http://localhost:8080/join/duple",{
id : id,
})
}
const signUp = async() => {
let res = await axios.post("http://localhost:8080/join/signUp",{
id : id,
pass : pass
})
console.log(res.data)
localStorage.setItem("token", res.data)
navigate("/todo")
}
I think, this isn't the best way, If you know of a better way than this, please advise.
Better to have another async function that does both things.
something like
const checkDupleAndSignUp = async () => {
await checkDuple();
await signUp();
};
And then use that in your useMutation instead.
Other things to consider:
Maybe move the logic to set local storage and navigate to another page in the onSuccess instead.
You can also throw your own error if one or the other request fails and then check which error happened using onError lifecycle of useMutation, and maybe display a message for the user depending on which request failed.
You can handle both of them in a single function and in mutation just add token in localStorage and navigate
like this:
const checkDupleAndSignUp = async () => {
return checkDuple().then(async res => {
if (res === false) {
return {
isSuccess: false,
message: 'Sorry, This mail is duplicatied',
};
}
const { data } = await signUp();
return {
isSuccess: true,
data,
};
});
};
and in mutation :
let loginQuery = useMutation(checkDupleAndSignUp, {
onSuccess: res => {
if (res.isSuccess) {
console.log(res.data);
localStorage.setItem('token', res.data);
navigate('/todo');
} else if (warning.current !== null) {
warning.current.innerText = res.message;
}
},
});
I call an API call when a button is clicked. in the console, it shows as the API call was a success.
Then upon the successful call, I call a print handler to print the screen. But the first time the button clicks, it shows as unsuccessful & when I click again it shows as successful.
Following is my code.
const ConfirmBooking = async() =>{
console.log("child",seatsSelected)
const adultTicketCount = seatCount - counter
console.log("adult",adultTicketCount)
const firstName = "Ryan"
const lastName = "Fonseka"
const email = "ryan#343.com"
const mobileNumber = "333333"
const customerDetails = {
firstName:firstName,
lastName:lastName,
email:email,
mobileNumber:mobileNumber
}
let seatDetails = []
let seatCatId = 2761
seatDetails.push({
seatCategoryId: seatCatId,
seatNumbers:seatNumbers,
childCount: counter,
adultCount: adultTicketCount
})
console.log(seatDetails)
let mounted = true
await BookingRequest(seatDetails,customerDetails) // this is the API call
.then(data =>{
if(mounted){
setBooking(data)
}
})
console.log(booking)
const status = booking
console.log(status.success)
if((booking.success) === true){
await printHandleOpen(booking)
} else {
alert("Booking Failed")
}
}
It seems that the problem could be on the line in the API call where you call setBooking(data). This will schedule a state update, but the update will only occur after this function is popped off the call stack, so in the if((booking.success) === true) line, this will only evaluate as expected on the second time through.
edit: adding suggested .then code block
.then(data => {
if(mounted){
setBooking(data)
await printHandleOpen(booking
}
})
.catch(err => {
alert("Booking Failed")
})
and then you can remove that if...else block that fires those methods later in the code.
// Get this out of the function 'ConfirmBooking'
if((booking.success) === true){
await printHandleOpen(booking)
} else {
alert("Booking Failed")
}
I am building feed news using reactjs, but however, I notice that Axios is not returning data back to my browser feed in order to process the data, what am I missing on this code?
const browserFeed = async () => {
const response = await browse();
console.log(response)
setFeed(response.data.results); // undefined
setIntialized(true);
};
export const browse = () => {
axios.get('xxxxxxxxxxx').then((result) => {
return result // undefined
}).catch((error) => {
return error;
})
}
You are missing returning the Promise axios.get returns.
export const browse = () => {
return axios.get('xxxxxxxxxxx').then((result) => {
return result;
}).catch((error) => {
return error;
});
};
You can simply return the Promise though, you don't need to chain another .then just to return the resolved value.
export const browse = () => {
return axios.get('xxxxxxxxxxx').catch((error) => {
return error;
});
};
And to be honest I don't think you want to catch and return the error here either since your component logic is written to assume success. You can return the Promise and handle any rejected promises in a try/catch.
export const browse = () => {
return axios.get('xxxxxxxxxxx');
};
But this is a little boring, may as well just make the axios call in the component. surround all the fetching logic in a try/catch, set the feed in the happy success branch, set any error state in the sad failure branch, and set the initialized state in finally block so no matter pass/fail you can indicate data was fetched.
const browserFeed = async () => {
try {
const response = await axios.get('xxxxxxxxxxx');
console.log(response)
setFeed(response.data.results);
} catch(error) {
// set any error state
} finally {
setInitialized(true);
}
};
This avoids the mixing of the async/await syntax with any promise-chain syntax, which should be avoided.
I am using a promise based hook in a React app to fetch async data from an API.
I am also using a Axios, a promise based http client to call the API.
Is it an anti-pattern to use a promise based client inside another promise? The below code does not seem to work.
const getData = () => {
return new Promise((resolve, reject) => {
const url = "/getData";
axios.get(url)
.then(function(response) {
resolve(response);
})
.catch(function(error) {
reject(error);
});
});
const useAsync = (asyncFunction) => {
const [value, setValue] = useState(null);
const execute = useCallback(() => {
setPending(true);
setValue(null);
setError(null);
return asyncFunction()
.then(response => setValue(response))
.catch(error => setError(error))
.finally(() => setPending(false));
}, [asyncFunction]);
useEffect(() => {
execute();
}, [execute]);
return { execute, pending, value, error };
};
};
const RidesList = () => {
const {
pending,
value,
error,
} = useAsync(getData);
Oh man. I think you have a fundamental misunderstanding about how Promises work.
First, axios already returns a Promise by default. So your whole first function of getData can be reduced to:
const getData = () => {
const url = "/getData"
return axios.get(url)
}
But the meat of your code seems to indicate you want a querable Promise - so you can check the status of it for whatever reason. Here's an example of how you would do it, adapted from this snippet:
function statusPromiseMaker(promise) {
if (promise.isResolved) return promise
let status = {
pending: true,
rejected: false,
fulfilled: false
}
let result = promise.then(
resolvedValue => {
status.fulfilled = true
return resolvedValue
},
rejectedError => {
status.rejected = true
throw rejectedError
}
)
.finally(() => {
status.pending = false
})
result.status = () => status
return result
}
In this way, you can then do something like let thing = statusPromiseMaker(getData()) and if you look up thing.status.pending you'll get true or false etc...
I didn't actually run what's above, I may have forgotten a bracket or two, but hopefully this helps.
I have to admit - I haven't seen anything like this ever used in the wild. I am interested in knowing what you're actually trying to accomplish by this.
Axios itself returns a promise but if you want to make a custom class having your custom logic after each API call then you can use interceptors I was having the same requirement and this is how I am returning promises after applying my custom logic on each API call.
Interceptors will get executed separately after and before each request you made so we can simply use them if we want to modify our request or response.
here is my working solution have a look at it.
callApi = (method, endpoint, params) => {
this.apiHandler.interceptors.request.use((config) => {
config.method = method
config.url = config.baseURL + endpoint
config.params = params
return config
})
return new Promise((resolve, reject) => {
this.apiHandler.interceptors.response.use((config) => {
if (config.status == 200) {
resolve(config.data)
} else {
reject(config.status)
}
// return config
}, error => reject(error))
this.apiHandler()
})
}
Below is the code to call this function
helper.callApi("get", "wo/getAllWorkOrders").then(d => {
console.log(d)
})
I'm trying to fetch webpages using axios and cheerio but i'm failing to retrieve all the data as a function is returning even before the intennal process is completely done. I'm using ReactJS and and when i click a button in the page, this function gets called :
analyse = async(e) => {
this.a = await axios.get('xxx');
this.s = await axios.get('yyy');
this.f = await axios.get('zzz');
let aReturn = this.fetchA(this.a.data);
let sReturn = this.fetchS(this.s.data);
let fReturn = this.fetchF(this.f.data);
if(await fReturn === true && await aReturn === true && await sReturn === true){
anotherFunction();
}
}
In the above code, the axios works fine and the functions fetchA() and fetchS() are simple functions without any further internal function calls :
fetchA(html){
const $ = cheerio.load(html);
//some process
return true;
}
fetchS(html){
const $ = cheerio.load(html);
//some process
return true;
}
The function that is returning without complete execution is fetchF() :
fetchF(html){
const $ = cheerio.load(html);
$('div._someClassName').children().each((i,elem) => {
let link = $(elem).find('a').first().attr('href');
axios.get(link)
.then(response => {
this.deepF(response.data);
})
.catch(err => {
console.log("Error : ",err);
})
};
return true;
}
In the above function there is a unique link in every child that i need to axios.get() again and call another function deepF() to grab the data of that page.
The internal function deepF is again a small function :
deepF(html){
const $ = cheerio.load(html);
//some process
return true;
}
In this whole code the fetchF() is returning true without completely executing all the deepF() functions internally.
Note : All the deepF() functions are executed slowly later after the fetchF() returns true
How can i wait for fetchF() to execute all the internal deepF() before returning true in fetchF()?
Change the implementation of fetchF() to properly return a promise that is linked to all the ajax calls. Accumulate the ajax promises into an array and then use Promise.all() to know when they are all done. Then, you can await the result of that function.
Change from this:
fetchF(html){
const $ = cheerio.load(html);
$('div._someClassName').children().each((i,elem) => {
let link = $(elem).find('a').first().attr('href');
axios.get(link)
.then(response => {
this.deepF(response.data);
})
.catch(err => {
console.log("Error : ",err);
})
};
return true;
}
to this:
fetchF(html){
const $ = cheerio.load(html);
const promises = [];
$('div._someClassName').children().each((i,elem) => {
let link = $(elem).find('a').first().attr('href');
promises.push(axios.get(link).then(response => {
return this.deepF(response.data);
}).catch(err => {
console.log("Error : ",err);
throw err;
}));
});
return Promise.all(promises).then(() => true).catch(() => false);
}
This makes fetchF() into a function that returns a promise that resolves only when all the axios.get() calls inside it are done and resolves with a true value. If there are any errors, it catches those errors and resolves with a false value (which seems to be the logic you wanted, though it's a bit unusual to not just let the rejected promise propagate and catch it at a higher level to signify errors).
Then, you can use:
let fReturn = await this.fetchF(this.f.data);
And, then fReturn will be true or false.
If any of your other functions have asynchronous operations in them, they will also need to return a promise that is directly linked to your asynchronous operations.