How to read attribute values from an array of objects? - javascript

I am working in node.js.
I make a rest api call in .js file as follows:
$http.get("/api/products/"+cat_id).success(
function(response){
//$scope.cat_id = response;
console.log("Got response products for page 1");
console.log("Received products for cat :"+response.pdt.cat_id);
}
)
The following code snippet is contained in a file app.js:
app.get('/api/products/:cat', function(req, res){
var pdts = [];
for(var i=0; i<=6; i++){
var pdt = {
id : "1" + i
, name: 'Product' + i
,cat_id: req.params.cat
};
pdts.push(pdt);
}
res.json(pdts);
});
The array of objects pdts is sent as a response through the last statement.
Now how do I access the individual attributes of my object pdt??
The result of
console.log("Received products for cat :"+response.pdt.cat_id);
is
Cannot read property 'cat_id' of undefined

You are returning an array of objects, so you need to loop through it and access each element individually:
$http.get("/api/products/" + cat_id).success(function(response) {
console.log("Got response products for page 1");
// response is an array of javascript objects
for (var i = 0; i < response.length; i++) {
var element = response[i];
console.log("Received products for cat :" + element.cat_id);
}
});
or if you wanted to access some element directly by index:
console.log("Received products for cat :" + response[0].cat_id);
Obviously it is recommended that you first check the size of the array to ensure that the element you are trying to access exists.

Related

I am trying to run two functions onLoad, one needs to run first so the second one can populate a boxlist, however, the second one doesn't get thearray

I have two functions that I am trying to run when I load the page. dataRetrieve() gets the data from a firebase collection. populate() is supposed to populate a boxlist with the entries retrieved from dataRetrieve(). The main problem is that it lists the array as empty when I run populate() after dataRetrieve() no matter what I try. The last thing I tried was this:
async function dataRetrieve(){
const getAdmins = firebase.functions().httpsCallable('getAdmins');
// Passing params to data object in Cloud functinon
getAdmins({}).then((results) => {
admins = results;
console.log("admins retrieved");
console.log(admins);
}).then(() => {
populate();
});
}
async function populate(){
let list = document.getElementById("user-list");
//loop through users in out Users object and add them to the list
for (var i = 0; i < admins.length; i++) {
let newItem = document.createElement('option');
newItem.innerHTML = admins[i].first + " " +admins[i].last;
newItem.id = admins[i].uid;
if (i == 0) {
newItem.className = "active";
}
console.log(newItem.innerHTML + " " + newItem.id)
list.appendChild(newItem);
}
updateResponse(list.firstChild);
list.size = admins.length;
console.log(document.getElementById("user-list").size)
//collect all the list items
let listItems = list.querySelectorAll('option');
//loop through the list itmes and add a click listener to each that toggles the 'active' state
for (var i = 0; i < listItems.length; i ++) {
listItems[i].addEventListener('click', function(e) {
if (!e.target.classList.contains('active')) {
for (var i = 0; i < listItems.length; i ++) {
listItems[i].classList.remove('active');
}
e.target.classList.add('active');
updateResponse(e.target);
}
})
}
}
also, admins is a global variable listed at the start of the script:
var admins = [];
I am trying to run all this onload so I can instantly generate the list
I thought that .next would cause it to wait to get the values before running, but even making results a parameter and transferring it directly into the function that way gives an undefined array. I don't understand why the function insists on calling on old data. Pls help.
I'm not sure what updateResponse function does. If it's not returning a promise then I'd make the populate function synchronous first. Also do you really need to use admins array somewhere else apart from populate function that it is a global variable? If not then I'd just pass it as a parameter.
async function dataRetrieve() {
const getAdmins = firebase.functions().httpsCallable('getAdmins');
// Passing params to data object in Cloud function
const results = await getAdmins({})
console.log("admins retrieved");
console.log(results);
// Passing results in populate function
populate(results.data)
// If your function returns an array, pass the array itself
}
function populate(admins) {
let list = document.getElementById("user-list");
//loop through users in out Users object and add them to the list
// Using a for-of loop instead so no need to worry about checking the length here
for (const admin of admins) {
let newItem = document.createElement('option');
newItem.innerHTML = admin.first + " " + admin.last;
newItem.id = admin.uid;
//if (i == 0) {
// newItem.className = "active";
//}
console.log(newItem.innerHTML + " " + newItem.id)
list.appendChild(newItem);
}
updateResponse(list.firstChild);
// rest of the logic
}
I guess you know how to check when the page loads. call the retrieve function when the page is loaded. Then you should call the populate function at the end of the retrieve function. this makes sure that the populate function is called after you get all the data

Parse Cloud Code Save All

So I have a list of about 200 rows in my Parse Core. I am trying to create a job that runs through the entire list and changes the entire column of push to 0. I am trying to do so with this code:
Parse.Cloud.job("SetPush", function(request, response) {
//take in JSON with dict
var newts = new Array();
for ( var i = 0; i < request.params.push.length; i++ )
{
//add these entries to db
var DataClass = Parse.Object.extend("AllTeams");
var dataupdate = new DataClass();
var origdata = request.params.datalist[i];
dataupdate.set("push", "0");
newts[i]=dataupdate; //add another item to list
}
Parse.Object.saveAll(newts,{
success: function(list) {
// All the objects were saved.
response.success("ok " ); //saveAll is now finished and we can properly exit with confidence :-)
},
error: function(error) {
// An error occurred while saving one of the objects.
response.error("failure on saving list ");
},
});
//default body does not do response.success or response.error
});
As you can see my class is SetPush and I want to update the push column all the way down. The problem I believe lies in this:
for ( var i = 0; i < request.params.push.length; i++ )
When I run this code in the Cloud Code, it returns this error:
'TypeError: Cannot read property 'length' of undefined at main.js:43:60'
What am I doing wrong? Thank you
.length is undefined because request.params.push is an object. Looks like you want to iterate through a list you're passing in to this cloud function using the input parameter request.params.push, if/assuming the caller is passing in a valid JSON as 'push' then you can do something like this
Parse.Cloud.job("SetPush", function(request, response) {
//take in JSON with dict
var parsedJson = JSON.parse( request.params.push );
var newts = new Array();
for ( var i = 0; i < parsedJson.length; i++ )
{
//add these entries to db
var DataClass = Parse.Object.extend("AllTeams");
var dataupdate = new DataClass();
var origdata = request.params.datalist[i];
dataupdate.set("push", "0");
newts[i]=dataupdate; //add another item to list
}
Parse.Object.saveAll(newts,{
success: function(list) {
// All the objects were saved.
response.success("ok " );
//saveAll is now finished and we can properly exit with confidence :-)
},
error: function(error) {
// An error occurred while saving one of the objects.
response.error("failure on saving list ");
},
}); //default body does not do response.success or response.error
});

Result: TypeError: Object [object Object] has no method 'set' when trying to edit Parse object

When I try to run the following background job, I get an error stating Result: TypeError: Object [object Object] has no method 'set', referring to the line where I attempt to set the 'Number' property of the object being returned to a value of 2. I've used this same format to edit Parse objects before, and it worked fine, what am I doing wrong here?
Parse.Cloud.job("sendLowPush", function(request, status) {
Parse.Cloud.useMasterKey();
/////////////
//send push notification to all users in the "lowPush" channel
//{Query the # value of pushIncrement with object id hKj2Eazz6h}
var pushIncrement = Parse.Object.extend("pushIncrement");
var pushIncrementQuery = new Parse.Query(pushIncrement);
pushIncrementQuery.equalTo('objectId', 'hKj2Eazz6h');
pushIncrementQuery.find({
success: function(results) {
for (var i = 0; i < results.length; ++i) {
var dayNumber = results[i].get("Number");
}
console.log('dem results be:' + dayNumber);
//Figure out whether its day 1, 2, or 3, and increment. Send lowPush if day 3.
if (dayNumber = 1){
//change it to 2
console.log('dayNumber is 1');
results.set('Number', '2');
results.save();
}
else if (dayNumber = 2){
//change it to 3
console.log('dayNumber is 2');
}
status.success("Push Notifications completed successfully.");
},
error: function(error) {
console.log('shit');
status.error('shitty shit');
}
});
});
results is the list of objects. You can't set the Number field on the whole list. However, it looks like you are only querying for a single object with a specific ID. In that case you should use .get instead:
pushIncrementQuery.get('hKj2Eazz6h', {
success: function(obj) {
var dayNumber = obj.get("Number");
// ...
obj.set('Number', '2');
obj.save();
}
});
If you want to use .find, you'd have to access the correct element in the list, i.e. either results[i] or results[0].

Can't read values that are outside of function

I am learning JavaScript and AngularJS. I want to use the values that are outside of function, but I don't know how to access them.
Here is my code (AngularJS Controller):
var init = function() {
$http.get('getSomeValues').then(function (res) {
var returnArray = res.data; // Result is array
for(var i=0; i < returnArray.length; i++) { // Loop through the array
console.log("THIS WORKS FINE: ", returnArray[i].value); // It works
$http.get('getOtherValues/' + returnArray[i].value).then(function (res) {
console.log("WHAT'S IN IT: ", returnArray[i].value); // Shows 'undefined' error
});
}
});
};
init();
So basically I want to access the array returnArray, but I can't. Is there any good way to access the values? I assume that '.then(function ..' causes error..
You'll need to use a IIFE:
Replace:
for(var i=0; i < returnArray.length; i++) { // Loop through the array
$http.get('getOtherValues/' + returnArray[i].value).then(function (res) {
console.log("WHAT'S IN IT: ", returnArray[i].value); // Shows 'undefined' error
});
}
With:
for(var i=0; i < returnArray.length; i++) { // Loop through the array
(function(data){
$http.get('getOtherValues/' + data.value).then(function (res) {
console.log("WHAT'S IN IT: ", data.value); // Shows 'undefined' error
});
}(returnArray[i]))
}
This ensures that, for the current iteration of the for loop, the data variable will be set to the current raturnArray item.

Getting undefined directly after logging object in Javascript

I have the following code...
var tagMap = {};
console.log("Data" + data);
console.log(JSON.stringify(data));
for(var item in data.results){
tagMap[item.path.key] = item.value.name;
}
But it outputs...
Data[object Object]
{ "count":1,
"total_count":1,
"results":[
{"path": {"collection":"ProcessedReports","key":"20140225.DIF","ref":"4802caab51897eae"},"value": {"name":"20140225.DIF"},"score":1}
]
}
undefined
project/routes/index.js:73
for(var item in data.results){
^
TypeError: Cannot read property 'results' of undefined
I am confused, how is it getting set back to null?
Update
Thanks to a comment I noticed the log was actually the following...
Data[object Object]
{"count":1,"total_count":1,"results":[{"path":{"collection":"ProcessedReports","key":"20140225.DIF","ref":"4802caab51897eae"},"value":{"name":"20140225.DIF"},"score":1}]}
Dataundefined
undefined
this leads me to believe the method is getting called 2x I will try to add more code asap.
Full route (expressjs) using orchestrate.io, still can't find the dual call. Only 1 call to getloadedfiles I can find so far in the source.
exports.getloadedfiles = function(req, res, next){
miao.search({
collection: 'ProcessedReports',
query: '*'
},
function (err, data) {
var tagMap = {};
console.log("Data" + data);
console.log(JSON.stringify(data));
for(var item in data.results){
tagMap[item.path.key] = item.value.name;
}
req.processed = tagMap;
return next();
});
}
With the grep of my project...
grep -r getloadedfiles ./
.//app.js:app.get('/files/list', routes.getloadedfiles, routes.getfiles, routes.renderfiles);
.//routes/index.js:exports.getloadedfiles = function(req, res, next){
It should probably be
for(var item in data.results){
tagMap[ data.results[item].path.key ] = data.results[item].value.name;
}
accessing the objects values with the key passed in the loop, otherwise you're doing
0.path.key
as in trying to access properties on the string that is the key, which won't work
FIDDLE
Another thing, data.results is an array, and should be iterated with
for (var i=0; i<data.results.length; i++) { ...
And then you'd end up with
for (var i=0; i<data.results.length; i++) {
tagMap[data.results[i].path.key] = data.results[i].value.name;
}
FIDDLE

Categories