Parse.com Relational Query - javascript

I am quite new to Parse and I am struggling with a particular query. I have a class User
a class Post
and a class Comment (I guess my configuration is pretty standard) I do not have enough reputation to post pictures - how sad that sounds - :-)
I have a query where basically I select all the posts (and the related users and ideally I would like to have all the comments related to the post) To do so I do:
var query = new Parse.Query("Post");
query.include("user");
query.find({
success: function(objects) {
for (var i = 0; i < objects.length; i++)
{
var object = objects[i];
console.log(object.id + object.get("user").get("imageUrl") + object.get('text'));
var commentquery = new Parse.Query("Comment");
commentquery.equalTo("post", object);
commentquery.find({
success: function(comments) {
console.log(object.id + object.get("user").get("imageUrl") + object.get('text'));
where basically I try to get the posts and then fetch the comments for each of them. Unfortunately, the second console log in my code always prints the same object (like ignoring the for loop).
I really don't know what am I doing wrong (maybe the callbacks or maybe the query setup) but I am not able to overcome this. Also, if any expert knows a better way of doing this without getting redundant with data or knows a good tutorial / book on Parse (apart from the Parse Documentation) I will be really grateful.
Thanks in advance!

Use an anonymous function to close your work on object.
for (var i = 0; i < objects.length; i++)
{
var object = objects[i];
(function(object){
//do stuff with object;
})(object);
}
You're using the most recent object because the work after the assignment has not yet finished so objects[i] is going to the next one too early. The extra function should help.
Or you can just
for (var i = 0; i < objects.length; i++)
{
(function(object){
//do stuff with object;
})(objects[i]);
}
Closures and the infamous loop problem

Related

Why is my loop running only once in a Google Sheet with Google Apps Script? [duplicate]

This question already has answers here:
Nested for-loop only executing once
(2 answers)
Closed 2 years ago.
I am unable to figure out on why my loop is running only once.
I am sitting here for like 2 hours to figure it out, but no luck.
please help
var tempSheetValues1 = currentSheet.getRange("B2:B" + lastRow).getValues();
// considering length to be 5
for (var i = 0; i < 5; i++) {
var id = tempSheetValues1.slice(i, i + 1).join('');
var url = 'https://api.demo.hitmebro/' + id + '?language=en';
Logger.log(url);
// Check if the test id exists
var response = hitApi(url, "get", null, headers, "inputId");
Logger.log(response);
var json = response.getContentText();
var data = JSON.parse(json);
var Collection = data.data.inside;
var rows = [];
data;
for (i = 0; i < Collection.length; i++) {
data = Collection[i];
var more = rows.push([data.xid]);
}
dataRange = currentSheet.getRange(2, 1, rows.length, 1);
dataRange.setValues(rows);
}
Preamble
Since comments to the question deal with the issue, I added several optimization points to consider, paying attention to them will benefit you in the long run.
Suggestions
Move to the new V8 runtime to make use of the latest ES6 features and syntax:
Make use of built-in Array methods, like map, reduce, filter, etc. - it improves readability, reduces probability of bugs creeping in (because you forgot to change i to j - exactly your case).
Use destructuring assignment - again, it improves readability and, especially if combined with TypeScript (or JSDoc) is a joy to use (+improved type safety).
Use const as much as you can (unless you really need to reassign - and use let then, not var), most certainly never use undeclared variables (I assume dataRange is defined somewhere prior to the code sample, but just in case...).
[edit] it might sound counter-intuitive, but variables aren't meant to be rewritten, the name refers to the fact that they can hold any value. Thus, please, avoid resetting (like let data = 'some_val'; data; data = 'new_val') - it leads to messy and / or buggy code. Instead, decalre a new one or try to avoid it at all (see below).
Optimized code
This is not the most optimal version there is, but is definitely a start (e.g., you can take the getRange() out of the loop to improve execution speed on large collections drastically, issue concurrent requests to the API with Promise.all() - thank V8 - etc.)
const tempSheetValues1 = currentSheet.getRange("B2:B" + lastRow).getValues();
for (let i = 0; i < 5; i++) {
const id = tempSheetValues1.slice(i, i + 1).join('');
const url = `https://api.demo.hitmebro/${id}?language=en`;
Logger.log(url);
// Check if the test id exists
const response = hitApi(url, "get", null, headers, "inputId");
Logger.log(response);
const json = response.getContentText();
const parsed = JSON.parse(json);
const { data } = parsed;
const { inside } = data;
const rows = inside.map(elem => [elem.xid]);
const dataRange = currentSheet.getRange(2, 1, rows.length, 1);
dataRange.setValues(rows);
}
Notes
Hopefully I didn't miss anything when rewriting the inner loop logic, feel free to correct me if something's wrong.
References
Variable declaration guide
Array built-in methods reference on MDN
Migrating to V8 runtime guide
Destructuring assignment guide on MDN

Generating new variables to save loop results

I´ll try to be very specific about this topic.
So I have a "for" loop in javascript working just fine. The loop aims to retrieve the URLs of all the files existing in a target folder. The question is, how can I save the retrieved URLs into individual variables?
So, in order to make things easy, I won´t paste the code I´m using, I´ll just create a simple array and run a "for" loop as an example, so you guys can tell me how you would try to save the results into new variables.
So here's the example:
var index;
var arrayElements = ["FirstURL", "SecondURL", "ThirdURL"]
for (index = 0; index < arrayElements.length; index++) {
document.write (arrayElements[index]+"<br/>");
}
So, with that code, I can "print" the different URLs included in the array (I could use console.log of course, but I´m writing in notepad++, so I have to test the code with document.write)
So the question, how can I save each URL into an individual variable?
EDIT:
Ok, so reading the first answers, I think I must clarify some things.
The question is that I need to store the URLs in variables so I can call them later. So it´s not a question about "printing" the URLs.
The function eval()
I know eval is bad
var data = ["a", "b", "c"];
function makeIndvidualVariable(array){
var size;
try{
size = array.length;
for(var i = 0 ; i < size ; ++i){
if( eval(array[i]) != undefined){
eval("var "+array[i]+"="+array[i]+";");
}else{
throw "already exist variable : "+array[i];
}
}
}catch(e){
console.log(e);
}finally{
array = size = i = null;
}
}
makeIndvidualVariable(data);
You can obtain individual variables with window object (if i got you properly).
Use the thing with JS that enables you to declare variables in window scope.
var index;
var arrayElements = ["FirstURL", "SecondURL", "ThirdURL"]
for (index = 0; index < arrayElements.length; index++) {
window['variable'+index] = arrayElements[index];
}
// now variables are available globally (through window object)
document.write(variable0); // prints FirstURL
document.write(variable2); // prints ThirdURL
// etc.
Hope this helps.
Just for the sake of printing the urls stored in array one by one and avoid loops you can use this:
document.write (arrayElements.join("<br/>"));

Object exists but is still undefined in youtube response?

I'm having a little trouble with some Youtube API JS. I have troubleshooted for a while and I have annotated my code with comments so that you understand what the problem is. I know that their are several different things thay might be wrong. Anyway thanks for helping out!
request.execute(function(response) {
console.log(response.result.items); // Here you get an array of objects.
var results = response.result;
console.log(results.items.length);
var id = results.items.id;
for (id in results.items) {
console.log(results.items.id); // And here it is undedfine. When adding video.Id the console says cannot read property videoId of undefined.
console.log('if you read this the loop works');
}
});
You are trying to access an id property on an array, which doesn't exist (hence, undefined). The main problem is that for in in JavaScript is for iterating through object keys, not arrays. Use a regular for loop:
request.execute(function (response) {
var results = response.result;
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
}
});
If you don't need to support IE8, you can use a .forEach().
(As a side note, read up a bit on for in with JavaScript, as your usage is a bit incorrect.)

Using "eval" in a couchdb reduce - just how dangerous is this?

My docs contain lists of errors.
I have a view which counts the number of docs with a specific error, and an average of how many errors a doc with a given error has.
Map
function (doc) {
var i;
for (i = 0; i < doc.errors.length; i = i + 1){
emit([doc.errors[i], doc.flummery], [1, doc.errors.length])
}
}
Reduce
function (key, values, rereduce) {
var avg = [];
var cnt = [];
var i;
for (i = 0; i < values.length; i = i + 1) {
avg.push(values[i][1]);
cnt.push(values[i][0]);
}
return [sum(cnt), eval(avg.join("+")) / avg.length]
}
I have read many times that the use of eval() is the path to madness, but I can't think of any way that it could really trip me up here. Is eval() safe in couchdb views?
Note that Oleg came up with the obvious answer, which is "don't do that, couchdb gives you a sum() function". It is obvious in this situation that eval() is not needed. However, should I ever require it, is it safe to use given that I'll have good control over my inputs?
Can't you use sum(avg) / avg.length instead?
eval have obvious drawback of calling full power of compiler: it is very resource heavy and introduces a big security hole unless you carefully sanitize your input.

Reading out a JS object

I have been messing around for a project I'm working on with arrays in JS. However, since this didn't work out, I had to turn to objects. Never having used these, I'm wondering about something fairly simple, yet complicated to me. I have the following code:
var ticket_amount = {};
var days = $(".t_days_" + ticket_id).val().split(',');
for(var i = 0; i < days.length; i++)
{
if (! ticket_amount[days[i]])
{
ticket_amount[days[i]] = 0;
};
ticket_amount[days[i]] += num_tickets;
}
This gives me my output as follows:
I now want to use the information in this object to display some more information. More specifically, I need to get both the date and the ticketnumber out so I can work with them in jQuery. I'm not sure how to do this, though.
I've tried stuff like:
for(tickets in ticket_amount) { }, for(var i = 0; i < ticket_amount.length; i++) {}, but none of these options seem to work. How do I get the information out in this specific case? Thanks a lot.
I won't be on the computer after posting this so I won't be able to answer to any questions for now, but I will find time for it tomorrow. Thanks in advance.
You were almost correct. This would print the data you need, for example.
for(ticket in ticket_amount)
{
console.log("Ticket:" + ticket + " amount: " + ticket_amount[ticket]);
}
EDIT:
of course, ticket in the above example should have been named just a tad better :)
for(day in ticket_amount){
// Here day contains the day, and ticket_amount[day] contains the number of tickets
alert(day+': '+ticket_amount[day]);
}

Categories

Resources