Pass value to nested parse.com query callback - javascript

So, using parse.com, I'm doing some nested queries... basically, getting an object and then retrieving its relations and doing some operations.
pageQuery.find({
success: function (results) {
var pages = [];
for (var result = 0; result < results.length; result++) {
var resArrayLength = pages.push(results[result].toJSON());
var indexOfLastPush = resArrayLength - 1;
console.log("resArrayLength = " + resArrayLength);
pages[indexOfLastPush].scrapeRules = new Array();
console.log("index of last push set to " + indexOfLastPush);
var relation = results[result].relation("RulesForPage");
//get the related scrape rules
relation.query().find({
success: function (rules) {
console.log("Found " + rules.length + " rules");
for (var i = 0; i < rules.length; i++) {
console.log("rule index = " + i);
console.log("Found rule " + rules[i].id);
pages[indexOfLastPush].AllRules = new Array();
pages[indexOfLastPush].scrapeRules.push(rules[i].id);
console.log("pushed rule " + rules[i].get("name") + " to page at index " + indexOfLastPush);
}
}
});
}
The problem I am seeing is that I am trying to indexOfLastPush to track an array index I need, but that value has changed by the time the call back has happened.
How can I pass it to the "success" callback so I have the index I need?
UPDATE: Thanks to #cggaurav for the excellent tip. Why does it seem like the answer to every JavaScript problem is to wrap your code in an anonymous function?

You have to have what is called a closure or an anonymous function for every relation.query() you make. See "More on lexical scoping" | http://mark-story.com/posts/view/picking-up-javascript-closures-and-lexical-scoping

Related

how to list all local storage on page properly in javascript?

I am trying to show all my localstorage items value on my index page but for some reason it is not showing. can anyone see what I am doing wrong in my code below. In my index page script I am looping thorough the length of local storage and trying to display them on screen, only thing that display is one item. Please help. thanks for your help.
here is my code (index page script):
document.addEventListener("DOMContentLoaded", function (event) {
var dataFromLocalStorage = "";
for (var i = 0; i < localStorage.length; i++) {
dataFromLocalStorage =
dataFromLocalStorage + " " + localStorage.getItem(`key${i}`);
}
document.querySelector("#content").innerHTML = dataFromLocalStorage; // Updating same thing
})
The other script where I load it to localStorage:
var addToTheContent = document.getElementById("canvas");
var scheduleEvent = document.getElementById("scheduleStartTime");
var candidateId = document.getElementById('candsId');
var getCandId = document.getElementById("candsId");
var displayCandId = candidateId.options[candidateId.selectedIndex].value;
var id = 1;
function addTheEvent() {
var showText = addToTheContent.innerHTML = displayCandId + " ( " + scheduleEvent.value + " ) ";
localStorage.setItem(`key${id}`, JSON.stringify(showText))
id += 1
localStorage.getItem(`key${id}`);
window.location = "/";
}
"key${id}" is a template string, you need to use backticks `` instead of quotation marks "".
You could also loop through localStorage as you normally would for most JavaScript objects:
for(var key in localStorage) {
if(localStorage.hasOwnProperty(key)) { // ignore the prototype methods
// Do whatever you want with key and value found here
console.log(key + ": " + localStorage[key]);
}
}
Typo: Use i instead id
var dataFromLocalStorage = localStorage.getItem(`key${id}`);
correct:
var dataFromLocalStorage = `localStorage.getItem("key${i}");
Another thing, You are updating same innerHTML
var dataFromLocalStorage = "";
for (var i = 0; i < localStorage.length; i++) {
dataFromLocalStorage =
dataFromLocalStorage + " " + localStorage.getItem(`key${i}`);
}
document.querySelector("#content").innerHTML = dataFromLocalStorage; // Updating same thing
// do something with localStorage.getItem(localStorage.key(i));
// missing template string 'key${id}'
var id = 1;
function addTheEvent() {
var showText = displayCandId + " ( " + scheduleEvent.value + " ) ";
localStorage.setItem(`key${id}`, JSON.stringify(showText));
id += 1;
window.location = "/";
}

Missing formal parameter on setTimeout function

I'm currently writing a script in google apps script to get a list of stores in a specific location that meet my text search. I'm trying to set a timeout function for when I'm trying to receive the next page of results from google places api, and for some reason it keeps telling me that error: setTimeout function is missing a formal parameter. I've looked at everything online and the way I have it in my code looks like all the other ways to execute that function. If anyone could help me out that would be great! Thanks!
Here is my setTimeout function
function setTimeout( function(){
while(tempPage != null){
count = count++;
var nxtUrl = "https://maps.googleapis.com/maps/api/place/textsearch/json?pagetoken=" + tempPage + "&location=41.661129,-91.530167&radius=8050&key=" + apiKey;
var tempResponse = UrlFetchApp.fetch(nxtUrl);
var tempJson = tempResponse.getContentText();
Logger.log(tempResponse);
tempPage = JSON.parse(tempJson).next_page_token;
Logger.log("Page count: " + count);
for(var j = 0; j < 20; j++){
var tempPlace = JSON.parse(tempJson).results[j];
Logger.log("Name: " + tempPlace.name);
Logger.log("Address: " + tempPlace.formatted_address);
}// end for loop
}// end while loop
}, 3000);
Google apps script does not use the setTimeout function. The solution is to use Utilities.sleep() function instead.
Utilities.sleep(3000);
while(tempPage != null){
count = count++;
var nxtUrl = "https://maps.googleapis.com/maps/api/place/textsearch/json?pagetoken=" + tempPage + "&location=41.661129,-91.530167&radius=8050&key=" + apiKey;
var tempResponse = UrlFetchApp.fetch(nxtUrl);
var tempJson = tempResponse.getContentText();
Logger.log(tempResponse);
tempPage = JSON.parse(tempJson).next_page_token;
Logger.log("Page count: " + count);
for(var j = 0; j < 20; j++){
var tempPlace = JSON.parse(tempJson).results[j];
Logger.log("Name: " + tempPlace.name);
Logger.log("Address: " + tempPlace.formatted_address);
}// end for loop
}// end while loop

Limit items in ajax request

I am requesting data from a json to fill a table. I want to limit to 5 the request.
jQuery.getJSON("data/data.json", function(data) {
var table = $("table");
$.each(data, function(id, elem) {
table.append("<tr class='text-center'><td>" + elem.dato1 + "</td><td>" + elem.dato2 + "</td></tr>");
});
})
Or another option is to add boolean key "active" to the data and that it brings me the data items with the value = true. How do i do this?
You can use .slice() to filter the returned array down to just the first 5 elements.
data = data.slice(0, 5);
Just use a simple for loop.
var json_arr, limit;
limit = 5; // set limit to whatever you like
json_arr = JSON.parse(json_data);
for(var i = 0; i < limit; i++;) {
var this_item = json_arr[i];
table.append(this_item); // do your thing
}
The best limit you can implement is on your own controller (where you get your data from)
But if you don't have access/don't want to change, you can simple achive this by JavaScript:
var limit = 5; //your Limit
for(var i in data){
if(i > limit) break;
var elem = data[i];
table.append("<tr class='text-center'><td>" + elem.dato1 + "</td><td>" + elem.dato2 + "</td></tr>");
}

JavaScript Callbacks for multiple functions

I'm currently trying to take results I have from an api controller, and have that json data added to a table in my razor view. I had some issues with the array I was using to fill the table not being filled with data before the table was created. I've tried to absolve that problem with callbacks, but I'm still inexperienced, and having trouble understanding from tutorials.
Here are the javascript function I have (and in order they must go 1. the $.getJson 2. the fillArray function 3. the AddToTable function) :
$(document).ready(function ()
{
$.getJSON('api/GetRestaurants/detroit').done(fillArray(data))
});
function fillArray(data, callback)
{
var restaurant =
{
Name: "",
PhoneNumber: "",
PlaceID: "",
Rating: 0,
Website: ""
};
var dataArray = new Array();
for (var k = 0; k < data.length; k++) {
restaurant.Name = data[k].Name;
restaurant.PhoneNumber = data[k].PhoneNumber;
restaurant.PlaceID = data[k].PlaceID;
restaurant.Rating = data[k].Rating;
dataArray.push(restaurant);
}
callback(AddToTable(dataArray));
}
function AddToTable(dataArray) {
document.getElementById("tbl").innerHTML =
'<tr>' +
'<th>Restaurant Name</th>' +
'<th>Restaurant PlaceID</th>'
for (var i = 0; i < dataArray.length; i++) {
+'<tr>'
+ '<td>' + dataArray[i].Name + '</td>'
+ '<td>' + dataArray[i].PlaceID + '</td>'
+ '</tr>';
}
}
The data is there, and the api controller call is successful, I just need to data to fill the array before the table uses that array.
I appreciate any help and/or comments, thanks guys :].
When you do the following:
$.getJSON('api/GetRestaurants/detroit').done(fillArray(data))
You are calling the fillArray() function and passing its result to the .done() function. Instead, you should be passing the fillArray function to the .done() function.
$.getJSON('api/GetRestaurants/detroit').done(fillArray)
I prefer to use an anonymous function when setting a callback. Then the named functions can have the signatures that make sense for them. The anonymous callback function, of course, has the signature required for it. The named functions are then called inside the anonymous callback function.
$(document).ready(function() {
$.getJSON('api/GetRestaurants/detroit').done(function(data) {
var restaurants = createRestaurantArray(data);
addRestaurantsToTable(restaurants);
});
});
function createRestaurantArray(apiData) {
var restaurants = []; // Preferred syntax over "new Array()"
for (var i = 0; i < apiData.length; i++) {
restaurants.push({
Name: apiData[i].Name,
PhoneNumber: apiData[i].PhoneNumber,
PlaceID: apiData[i].PlaceID,
Rating: apiData[i].Rating,
Website: ""
});
return restaurants;
}
function addRestaurantsToTable(restaurants) {
var html = '<tr>'
+ '<th>Restaurant Name</th>'
+ '<th>Restaurant PlaceID</th>'
+ '</tr>';
for (var i = 0; i < restaurants.length; i++) {
html += '<tr>'
+ '<td>' + restaurants[i].Name + '</td>'
+ '<td>' + restaurants[i].PlaceID + '</td>'
+ '</tr>';
}
$('#tbl').html(html);
}
Also, your fillArray() function was creating a single restaraunt object and pushing that same object to the array for each iteration of the for-loop. That means the resulting array would contain the same object over and over, and that object would have the property values set by the last iteration of the loop.
All the commands in your fillArray function appear to be synchronous (i.e. the code does not move on until they are completed) so as long as this is called before your function to add the data you should be okay.

A way to set property of array contents?

I've got an inventory script that I'm using to create a readout of the players inventory from an array. I need to set a .amount property, but I'm getting some undefined errors when I try to set them like this. I can't use sets or hashmaps. Can anybody tell me what I'm missing?
I'm using NaN only to debug the code at the moment.
//This is already defined as an array, just a shortcut.//
var inv = state.history[0].variables.player.inventory;
inv[i].amount = 0;
//Do this for every item in the inventory.//
for (var i = 0; i < inv.length; i++) {
//If the inventory item is Apple should resolve to ...inventory.Apple.amount.//
var q = inv[i].amount;
//If we find a duplicate in the array, just count and keep going.//
if (inv[i] == inv[i-1]){
q = (q + 1);
//If the item is the last one or unique, print the item on the inventory screen.//
} else {
q = (q + 1);
alert(inv[i] + " " + q.NaN);
new Wikifier(place, inv[i] + " " + q.NaN + "<br>");
}
}
You are trying to get i before it is defined in the loop, put it after:
//This is already defined as an array, just a shortcut.//
var inv = state.history[0].variables.player.inventory;
//Do this for every item in the inventory.//
for (var i = 0; i < inv.length; i++) {
inv[i].amount = 0;
//If the inventory item is Apple should resolve to ...inventory.Apple.amount.//
var q = inv[i].amount;
//If we find a duplicate in the array, just count and keep going.//
if (inv[i] == inv[i-1]){
q = (q + 1);
//If the item is the last one or unique, print the item on the inventory screen.//
} else {
q = (q + 1);
alert(inv[i] + " " + q.NaN);
new Wikifier(place, inv[i] + " " + q.NaN + "<br>");
}
}

Categories