How to access members of a object in node.js - javascript

I'm really new to node.js and having a bit of a problem with objects. Lets say I have two files, one called printer.js and another called database.js. printer.js prints the results database returns. printer.js looks like this:
var db = require("./database")
db.getStations(dbReturn);
function dbReturn(stations) {
for(var i = 0; i < stations.length; i++) {
console.log('id: ' + stations.id);
}
}
and my database.js looks like this:
function getStations(callback){
var listOfStations = [];
for(var index = 0; index < 10; index++) {
var station = new Station(index);
listOfStations[index] = station;
}
callback(listOfStations);
}
function Station(id){
this.id = id;
}
exports.getStations = getStations;
I would just like to mention that Station class has a lot more members than that. But the problem here is that I cannot access the members from the Station objects I created in database.js from printer.js. I am having quite a bit of trouble figuring out how to do this. I have learned how to create a new object of Station in printer.js by exporting Station, but I still can't access the members of an object I created somewhere else! It just spits out 10 x "id: undefined"
I have been suggested to do something similar to this:
database.prototype.getStations = function(callback) {
//...
}
database.prototype.Station = function(id) {
//...
}
module.exports = database;
But this does not seem to work since it just tells me that database is undefined. What am I doing wrong here?

You're not accessing the stations by index in your for loop.
Change this in printer.js:
console.log('id: ' + stations.id);
to:
console.log('id: ' + stations[i].id);

Related

Getting an object within a query in MongoDB

I'm using MongoDB for the first time and having some difficulty. I'm trying to get an object from the database and then set properties of this object to be other objects in the database.
app.get('/photoCollection/:id', function (request, response) {
var id = request.params.id;
var query = Photos.find({user_id: id});
query.select("_id user_id comments file_name date_time").exec(function(err, info) {
if (info === null) {
console.error('Photos for user with _id:' + id + ' not found.');
response.status(400).send('Not found');
}
infoParsed = JSON.parse(JSON.stringify(info));
for (let i = 0; i < infoParsed.length; i++) {
for (let j = 0; j < infoParsed[i].comments.length; j++) {
let commenter_id = infoParsed[i].comments[j].user_id;
delete infoParsed[i].comments[j].user_id;
let commenterQuery = User.findOne({_id: commenter_id});
let commenter;
commenterQuery.select("_id first_name last_name").exec(function(err, info) {
commenter = info;
});
infoParsed[i].comments[j].user = commenter;
}
}
response.status(200).send(infoParsed);
});
});
I've tried this a few ways, and with this way (my most recent try), I'm getting the commenter is undefined. I haven't seen queries used like this, so I'm not surprised, but I was wondering if there was a better way to get something from the database during a query. Any help would be appreciated!

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

Cordova SQL - Select data from multiple table

I have a few tables in my SQLite database and each of them have a foreign key that tie each other.
Lets say the structure are like:
Person
=========
Id
Name
Income
=========
IncomeId
PersonId
Income
Contact
=========
ContactId
PersonId
ContactName
The PersonId in both income and contact table are foreign key to the Person table.
Now when i want to query out the data from all the tables, first i select from Person, then in the callback, i will loop through the data, and select from Income and Contact for each of the record. I can't do a join select as the data are not mandatory, i.e. for a Person it might have income but not contact, or vice versa.
However when i try to run through the loop, i found that the result is always the last instance of the data. After some googling the issue seems to be that i need to use Closure.
I tried to implement it but is having a hard time, currently my code looks like this:
for (var i = 0; i < len; i++){
var profile= results.rows.item(i);
var IdAir = profile["IdAir"];
console.log('processing AIR Id: ' + IdAir);
function queryIncomeSuccess(tx,incomeAirResult, currentLoop){
var lenIncomeAir = incomeAirResult.rows.length;
var incomeAIR = {};
if(lenIncomeAir > 0){
incomeAIR = incomeAirResult.rows.item(0);
}else{
incomeAIR = null;
}
if(currentLoop == len - 1)
{
profile["Income"] = incomeAIR ;
airJson[airJson.length] = profile;
}
};
function queryIncome(tx) {
tx.executeSql("SELECT * FROM Income WHERE IdAir = ?",
[IdAir], function(resultSet){
queryIncomeSuccess(tx,resultSet,i);
}, errorCB);
};
db.transaction(queryIncome, errorCB);
}
Is there any guide for multiple select for Cordova? Any help is greatly appreciated. Thanks.
Am able to get this done by using nested function and closure.
The thing to note is that, the closure need to apply at the db.transaction function, rather than on the success callback only.
Code structure used:
//inside for loop of first select result
for (var i = 0; i < len; i++){
function buildSuccessCallback(current,profile){
return function(tx, result){
querySuccess(tx, result,current,profile);
};
}
function querySuccess(tx,result,currentIdx,profile){
//...perform logic
console.log('currentIdx: ' + currentIdx); //returning the correct value
console.log('current Id: ' + profile["IdAir"]); //returning the correct Id
}
db.transaction((function(i,profile){
return function(tx){
tx.executeSql(mySQL, [profile["IdAir"]], buildSuccessCallback(i,profile), errorCB);
};
})(i,profile), errorCB);
}
Thanks.

I cant read params value from req.params in restify (node JS)

I am trying to read the parameters value from req.params but in a different way (I am trying to make an API in RESTIFY).
First I read the keys that are available in req.params, like;
var requestData = Object.keys(request.params);
And than I loop through each key and try to fetch its value. below is the code;
for(i = 1; i < requestData.length; i++) {
keyValue = requestData[i];
console.log(request.params.keyValue);
}
But the output shows me UNDEFINED.
Reason: I am trying to read the parameters this way because, then, I do not need to know the name of each parameter.
Below is the complete code:
var restify = require('restify');
var assert = require('assert');
var server = restify.createServer();
var client = restify.createStringClient({
url: 'http://example.com'
});
function onRequest(request, response, next)
{
console.log(request.params);
var requestData = Object.keys(request.params);
var customJsonString = '';
var keyValue = '';
for(i = 1; i < requestData.length; i++) {
keyValue = requestData[i];
console.log(request.params.keyValue);
customJsonString += "" + requestData[i] + " : " + requestData[i] + ", ";
}
console.log(customJsonString);
}
function start()
{
server.use(restify.fullResponse()).use(restify.bodyParser());
server.get(/^\/(.*)/, onRequest);
server.post(/^\/(.*)/, onRequest);
server.listen(8888);
console.log("Server has started.");
}
exports.start = start;
I will really appreciate any help regarding this issue.
Try this instead:
console.log(request.params[keyValue]);
request.params.keyValue means Give me the value of the property keyValue, whereas the code above means Give me the value of the property whose name is stored in the variable keyValue.
Also, are you sure you want to start with i = 1? Javascript-arrays are 0-based, so I think you want i = 0 instead.
It could help if you can give us the URL you are testing right now as well as the console output your get.
However, please note that arrays in Javascript have 0 based index and your loop should look like this:
for(var i = 0; i < requestData.length; i++) {
}
To loop through the properties of an object, you should probably use for..in anyway:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
I don't know if that will solve your problem but it's a start.

Simpy cannot iterate over javascript object?

I have scoured the other question/answer for this and implemented everything and I still cannot access the values of the object. Here's the code I am using:
function apply_voucher(voucher) {
var dates = $.parseJSON($("[name='dates']").val());
var voucher_yes_no = new Array();
var voucher_reduction = new Array();
if(voucher.length > 0)
{
$.each(dates, function(room_id, these_dates) {
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_yes_no.push('yes');
voucher_reduction.push(result.voucher_reduction);
} else {
voucher_yes_no.push('no');
}
}, 'json');
});
// check if there are any yes's in the array
if('yes' in voucher_yes_no) {
console.log("no yes's");
} else {
console.log(voucher_reduction);
console.log(typeof voucher_reduction);
for (var prop in voucher_reduction) {
console.log(prop);
console.log(voucher_reduction[prop]);
if (voucher_reduction.hasOwnProperty(prop)) {
console.log("prop: " + prop + " value: " + voucher_reduction[prop]);
}
}
}
}
}
Apologies for the constant console logging - I'm just trying to track everything to make sure it's all doing what it should. The console output I get from this is below:
...which shows the object containing one value, "1.01" and my console.log of the typeof it to make sure it is actually an object (as I thought I was going mad at one point). After this there is nothing from inside the for-in loop. I have tried jquery's $.each() also to no avail. I can't understand why nothing I'm trying is working!
It does not work because the Ajax call is asynchronous!
You are reading the values BEFORE it is populated!
Move the code in and watch it magically start working since it will run after you actually populate the Array!
function apply_voucher(voucher) {
var room_id = "169";
var dates = $.parseJSON($("[name='dates']").val());
var voucher_reduction = new Array();
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_reduction.push(result.voucher_reduction);
}
console.log(voucher_reduction);
console.log(typeof voucher_reduction);
for (var prop in voucher_reduction) {
console.log(prop);
console.log(voucher_reduction[prop]);
if (voucher_reduction.hasOwnProperty(prop)) {
console.log("prop: " + prop + " value: " + voucher_reduction[prop]);
}
}
}, 'json');
}
From what it looks like, you plan on making that Ajax call in a loop. For this you need to wait for all of the requests to be done. You need to use when() and then(). It is answered in another question: https://stackoverflow.com/a/9865124/14104
Just to say for future viewers that changing the way I did this to use proper deferred objects and promises, which blew my head up for a while, but I got there! Thanks for all the help, particularly #epascarello for pointing me in the right direction :) As soon as I started doing it this way the arrays began behaving like arrays again as well, hooray!
Here's the final code:
function apply_voucher(voucher) {
var booking_id = $("[name='booking_id']").val();
var dates = $.parseJSON($("[name='dates']").val());
if(voucher.length > 0) {
var data = []; // the ids coming back from serviceA
var deferredA = blah(data, voucher, dates); // has to add the ids to data
deferredA.done(function() { // if blah successful...
var voucher_yes_no = data[0];
var voucher_reduction = data[1];
if(voucher_yes_no.indexOf("yes") !== -1)
{
console.log("at least one yes!");
// change value of voucher_reduction field
var reduction_total = 0;
for(var i = 0; i < voucher_reduction.length; i++) {
reduction_total += voucher_reduction[i];
}
console.log(reduction_total);
}
else
{
console.log("there are no yes's");
}
});
}
}
function blah(data, voucher, dates) {
var dfd = $.Deferred();
var voucher_yes_no = new Array();
var voucher_reduction = new Array();
var cycles = 0;
var dates_length = 0;
for(var prop in dates) {
++dates_length;
}
$.each(dates, function(room_id, these_dates) {
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_reduction.push(result.voucher_reduction);
voucher_yes_no.push('yes');
} else {
voucher_yes_no.push('no');
}
++cycles;
if(cycles == dates_length) {
data.push(voucher_yes_no);
data.push(voucher_reduction);
dfd.resolve();
}
}, 'json');
});
return dfd.promise();
}
Can you show how voucher_reduction is defined?
I am wondering where the second line of the debug output comes from, the one starting with '0'.
in this line:
console.log(vouncher_reduction[prop]);
^
The name of the variable is wrong (then) and probably that is breaking your code.
I think there are no problem with your loop.
But perhaps with your object.
Are you sure what properties has enumerable ?
Try to execute this to check :
Object.getOwnPropertyDescriptor(voucher_reduction,'0');
If it return undefined, the property was not exist.

Categories