Dialogflow: Is this being used in an async call - javascript

I'm new to the javascript world and have been tinkering with Actions on Google. I had an action that was previously running but after attempting to simplify my code, I've been running into a new error I cannot seem to figure out. The code is supposed to make a call to a database and return information to the user based on the date they have selected.
Problem:
The code is supposed to make a call to a database and return information to the user based on the date they have selected. The intent seems to break down when I call the URL using axios. When I test my function I receive the following error from the Google Cloud Platform: "Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler?"
app.intent('Moon', (conv, {date}) => {
// Sets date to today if none given
if (!date) {
date = new Date().toISOString();
}
// Slices date string to match date format in database
const dateSlice = date.slice(5, 9);
// Call to row in dabase for the given date
function getData() {
return axios.get(`example.com/search?Date=${dateSlice}`);
}
return getData().then(res => {
res.data.map(con => {
conv.ask(`On X date there will be a ${con.Object1}`);
});
});
});
I don't know much about Promise and await but that seems to be the issue. I'm not sure how I was able to get my code to run before without these objects. I've tried to insert a Promise object before my return but it makes the rest of the function unreachable. I also checked to see if Axios had any updates but it has not, I am on the latest version. Does the error have to do with one of the returns perhaps?

It could be related to Promises, but you seem to be handling them correctly.
The call to axios.get() is returning a Promise...
... which you are returning in getData()...
... which is returned in the 'Moon' Intent handler as part of the getData().then() block.
I suspect more that this is a logic problem. If res.data is an empty array, then there will be no calls to conv.ask(), so you end up not asking anything.
There is also a problem if res.data has more than two items. In this case, you'll generate an error because you've replied with more than two "simple" responses.
Either way - you may wish to log res and/or res.data to make sure you're getting back what you think.

Related

How do I get the results from an action called in my saga?

In my payments saga I'm putting an action which hits Stripe and creates a payment, then returns that JSON as a string
const order = yield put(createOrderFromStripe(token, loginEmail, email));
so order.data.createOrder.orderString is what I'm looking to work with.
Right now the only way I can access this data is if I do order.then(o => { console.log(o.data.createOrder.orderString)
I'd rather not do the then and just do something on the next line like JSON.parse(order.data.createOrder.orderString). Doing this creates an async issue obviously, trying to access .data.... before order is filled with a value.
I must be missing something small here. Any help would be appreciated. Thanks!

Firestore - Query, then update

I want to return an item with a specific ID and perform an update operation on it. My query gets the right result, but it won't let me update it.
I tried following this tutorial: https://www.youtube.com/watch?v=mYyPbfpoZeM
And read the documentation. Both didn't help. Other threads to the same topic are, well, different.
I have a database of objects which have a unique ID stored as integer.
I have an HTML form to get an ID as user input and the query below to retrieve the according object.
I tried this. The query worked, the update didn't.
db.collection('objects').where('ID','==', ID ).get().then((snapshot) => {
snapshot.docs.forEach( doc => {
console.log('debug');
console.log(doc.data().ID);
})
});
I am still new to firebase and js, so please forgive me if my code is uterly wrong.
I am currently stuck with this:
db.collection('objects').where('ID','==', ID ).get().then((doc) => {
console.table(doc);
});
Which is still not working.
For the second snippet an I currently get an unlegible table in which I can't really find the object I was looking for.
How do I update a single value in a single document?
EDIT: I forgot my implementation attempts of the update function.
I tried doc.update({value:0}) inside the for loop in snippet one which yielded doc.update is not a function. Similarly for doc.data().update(...).
In the second snippet I mainly tried to see what I got returned and ran variations of the above mentioned uodate function. With no success.
I managed to get it to work by studying the part of the firestore documentation that goes more into detail about the actual functions. Somehow it was hard for me to find this.
db.collection("users").where("name", "==", somename).limit(1).get().then(query => {
console.log(query);
const thing = query.docs[0];
console.log(thing.data());
let tmp = thing.data();
tmp.current_game_play = tmp.current_game_play + 1;
console.log(tmp);
thing.ref.update(tmp);
});
So I use where to get a Query object, use get to get a a querySnapshot inside the then promise resolve, use docs[0] to retrieve the first (and only) documentSnapshot and finally ref to get a reference that makes the whole thing updatable later.
try this:
var objectRef= db.collection("objects").doc(ID);
objectRef.update({
value: 0
}).then(function() {
console.log("Document successfully updated!");
}).catch(function(error) {
// The document probably doesn't exist.
console.error("Error updating document: ", error);
});

Can not print data from API request

I am trying to learn working with API calls and responses and I needed a basic value that comes from api response but I wasn't able to get it work. So here is my problem;
(function worker() {
$.get('URL', function(data) {
$('#numbers').html(data); });
})();
I use this code and this works perfectly fine, and writes the API response to my HTML page. Also the API calls return the value in this format;
{
"success":"true",
"field1": {"number1":"number1_val","number2":"number2_val"},
"field2": {"number11":"number11_val","number22":"number22_val"}
}
Now, I tried to write the values from API response and I was successfull for writing the "success" value like this;
$('#success_val').html(data.success);
It printed true value to my HTML website in given #success_val field. However, when I tried to write the field1, or the first value of field1, I wasn't successful. I tried
$('#numbers').html(data.field1); => No success, empty page
$('nu#mbers').html(data.field1[0]); => No success, empty page
So, at this point, what I need to store & use is the "number11" value from field 2. I have read and searched for over an hour and found out that this api return is not a valid "array" return, instead it is called "field" (I might be wrong), but I couldn't find any info about how can I get the "number11" data from this api response.
$('#numbers').html(data.field1); => No success, empty page
Does data.field1 exist for sure? or spelling check.
you can get keys by Object.keys(data).
If exist data, it return ["success", "filed2", "field2"].
In the same way, you already know key, like number11,
data.field2.number11 or data["field2"]["number11"] return value.
If you don't know key, data["filed2"][Object.keys(data)[0]] return value
Thanks to https://stackoverflow.com/users/10366589/sh-k I have solved the problem in given way;
As I wasn't able to print output from field2 to HTML, I have checked keys at field2 with this code;
alert(Object.keys(data.field2));
and it returned
number11,number22
since I only needed number11 from that API response, I did the following;
var.storednumber = Object.keys(data.field2);
var.storednumber = storednumber[0];
$('#numbers').html(storednumber);
and I was able to get the number I wanted printed on the screen without any problem :)
There could be a better solution or fix for the issue I am having, but for now, this has solved. I guess the problem lies on the API response type as it doesn't return an array formatted data.

Parse Server Upset Data in loop

I'm trying to query an API to get some data then I want to upsert all of it into my table.
But for some reason I'm not having any luck.
What's the best way to go about this?
I don't think my method of doing a query in a loop is best.
var coin = new Parse.Object.extend("Coins");
axios.get('https://api.coinmarketcap.com/v1/ticker/')
.then(response => {
let data = response.data;
// Put into database
data.map(entry => {
let q = new Parse.Query(Model.Coins.className());
q.equalTo('symbol', entry.symbol);
q.first()
.then(record => {
record.set('symbol', entry.symbol);
record.set('price_usd', entry.price_usd);
return record.save(null, {useMasterKey: true});
});
});
res.success(response);
});
you should avoid fetching and updating objects in a loop. In order to make it better you need to use 2 things:
In your query, instead of using equalTo and first you need to use containedIn for query all the records in one call. Then you need to iterate on the query results, for each record in the loop you need to do the following:
record.set('symbol', entry.symbol);
record.set('price_usd', entry.price_usd);
Finally you need to use saveAll to save all the objects in one call (please notice that saveAll is static function of Parse.Object and you should pass an array into it. Please review the docs before doing it)
Check your data. You may find you have unexpectedly updated records.
Assuming that's the entire body of a cloud function, your function initiates an asynchronous server call, then immediately tells the requestor that the operation was successful, but response isn't populated yet so you pass back undefined. However, parse-server will still run that asynchronous code.
The solution is to put the res.success call inside another .then chain, so the function won't return a response until after the server call + save finishes.
You're also going to get an uncaught error if the symbol doesn't exist on your table, though. You don't check to make sure the query returned a response to the first() call.

JavaScript - Promise fulfilled too early?

I created a small sample application using VueJs and created a C# REST API to store and retrieve data in a SQL Server back end.
For testing, I created a simple web page with a form to create a "note". The note is stored by the following function, 'saveData()':
saveData()
{
let promiseStack = [];
var jsondata = JSON.stringify(this.note);
promiseStack.push(this.$http.post('REST_API/note', jsondata));
Promise.all(promiseStack).then(data =>
{
this.$http.get('REST_API/note');
this.$router.push({ name: 'viewnotes', params: { id: data[0].body.id }})
}, error =>
{
console.log(error);
});
}
I tried to use a promise to wait until the 'store' operation in the backend is complete, and issue a GET request to retrieve all notes once the promise is fulfilled.
However, the get request inside the promise doesn't return any data. If I issue the get request manually later one, I retrieve the data that was stored previously.
So I had look into the C# REST API. There are currently two functions: createNote(...), getAllNotes(...). I used a StreamWriter to log to the filesystem when these functions are called, using milisecond precision. What I see is that 'createNote' is called after 'getAllNotes'. So I suspect that the API is working correctly, but something with the way I'm using promises seems to be awfully wrong.
Maybe somebody has a hint?
UPDATE
I know that the GET request doesn't return any data by using the developer toolbar in Chromium. The response is empty
The developer toolbar in the network tab shows that the requests are submitted in the correct order, so the "POST" request is issued first
It seems I found the problem. I had a 'href' tag in my 'Save' link, which triggered an early routing. The intended 'POST' and 'GET' were fired correctly, but there was another 'GET' inbetween somewhere because of the 'href' tag in the link, even though it was empty.
I removed the tag, now it works as intended.

Categories

Resources