nodeJS create dynamic array and use as response - javascript

Hi i am creating an empty array then populating it with data from a mongo query using a forEach Loop.
i have been attempting this now for 4 days and nothing i seem to do is working i know im close but being a newbie to javascript and MEAN stack i just cant figure it out.
i have attached the code with comments on everything i am trying to do.
please any help would be awesome..
var mongoose = require('mongoose'),
User = require('../../models/UserModel'),
async = require('async');
module.exports.getfollowing = function(req, res){
//grab the Users ID from the body
var thefollower = req.body.follower;
//create empty array that i want to populate with the followee's ID and Avatar url
var obj = [];
//query mongo for the user
User.findOne({ _id: thefollower }, function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
//grab the following element of the users mongo schema -- should return all the followee's ID's -- tested works
var following = user.following;
//iritate throught all the followee's
async.forEach(following, function(item, callback) {
//current followee
var user = item;
//query mongo for the followee
User.findOne({_id: user}, function(err, followee, callback){
//get followee's ID and Avatar url
var id = followee._id;
var avatar = followee.avatar;
//add the followee's ID and Avatar url to the obj array
obj.push({
id: id,
avatar: avatar
});
});
//see if this worked - returns empty
console.log(obj);
callback();
}, function(err) {
//see if this worked - returns empty
console.log(obj);
//respond to the client - returns empty
res.json(obj);
});
}
});
};

You need to move your callback(); that is at the end of your async.forEach() callback to inside the User.findOne({_id: user}, ...) callback (right after you call obj.push()) because that is when you are actually done with item. With your current code you are telling the async module immediately that you are done with item, before your mongo query has a chance to complete.

mscdex
Was spot on his answer solved my issue for future help to others here is the code
var mongoose = require('mongoose'),
User = require('../../models/UserModel'),
async = require('async');
module.exports.getfollowing = function(req, res){
//grab the Users ID from the body
var thefollower = req.body.follower;
//create empty array that i want to populate with the followee's ID and Avatar url
var obj = [];
//query mongo for the user
User.findOne({ _id: thefollower }, function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
//grab the following element of the users mongo schema -- should return all the followee's ID's -- tested works
var following = user.following;
//iritate throught all the followee's
async.forEach(following, function(item, callback) {
//current followee
var user = item;
//query mongo for the followee
User.findOne({_id: user}, function(err, followee){
//get followee's ID and Avatar url
var id = followee._id;
var avatar = followee.avatar;
//add the followee's ID and Avatar url to the obj array
obj.push({
id: id,
avatar: avatar
});
//see if this worked - returns empty
console.log(obj);
callback();
});
}, function(err) {
//see if this worked - returns empty
console.log(obj);
//respond to the client - returns empty
res.json(obj);
});
}
});
};

Related

Can not insert id number using postman

This is the code in nodejs:
//Insert an employee
app.post('/employees', (req, res) => {
let emp = req.body;
var sql = "SET #EmpID = ?; SET #Name = ?; SET #EmpCode = ?; SET #Salary = ?; \
CALL EmployeeAddOrEdit(#EmpID,#Name,#EmpCode,#Salary);";
mysqlConnection.query(sql,[emp.EmpID, emp.Name, emp.EmpCode, emp.Salary],(err, rows, fields) => {
if (!err)
rows.forEach(element => {
if (element.constructor == Array)
res.send('Inserted employee id : ' + element[0].EmpID);
});
else
console.log(err);
})
});
I don't know if you will be able to see the image.
In the postman it keeps giving me this message:
Inserted employee id : null
Not getting the id number. In mysql workbench created the db with all the data proper settings, had 4 names, the delete process with postman was successful, but can't simply insert the data
You cannot return more than one response. So you can't use res.send in a loop.
But you can create an array and add all the ids to the array and present them in the response.
//Insert an employee
app.post('/employees', (req, res) => {
let emp = req.body;
var sql = "SET #EmpID = ?; SET #Name = ?; SET #EmpCode = ?; SET #Salary = ?; \
CALL EmployeeAddOrEdit(#EmpID,#Name,#EmpCode,#Salary);";
const container = []; //Create an empty array
mysqlConnection.query(sql, [emp.EmpID, emp.Name, emp.EmpCode, emp.Salary], (err, rows, fields) => {
if (!err) {
rows.forEach(element => {
if (element.constructor == Array)
container.push(row.insertedId); //Push the ids to the array
});
res.send('Inserted employee ids : ' + container.join());
}
else
console.log(err);
})
});

How to pass mysql query in function and get the results

Hello I have database and queries written in a module and I am calling the module from the main class. What I want is to pass a query in function and get results. This is what I am doing so far
database.js
var pool = mysql.createPool({
host : 'localhost',
user : 'xxxx',
password : 'xxx',
database : 'xxx'
});
exports.executeQuery=function(query,callback){
pool.getConnection(function(err,connection){
if (err) {
console.log("error comes " + err);
callback(true);
return;
}
connection.query(query,function(err,results){
connection.release();
if(!err) {
console.log("no error");
callback(false,{rows: results});
}
// check null for results here
});
connection.on('error', function(err) {
callback(true);
return;
});
});
};
and in my main class
var db = require('./database');
var user_id = 5
var query = "SELECT * FROM contacts WHERE user_id = ?", user_id;
db.executeQuery(query, function(r,contact_details) {
console.log("success");
console.log(contact_details);
});
It doesn't work. It doesn't even go inside the function or prints success string. But If I do query this
var query = "SELECT * FROM contacts";
This will work. But I want to send a conditional query and because of conditional query, it doesn't work. Don't know how to send a conditional query, for example, this query
var query = "SELECT * FROM contacts WHERE user_id = ?", user_id;
or
"SELECT count(*) as count FROM user_info WHERE user_id = ? AND phone_no_1 = ? OR phone_no_2 = ? OR phone_no_3 = ?",[user_id,formatted_sms_no,formatted_sms_no,formatted_sms_no],
These kind of queries. Any help would be appreciated.
Thank you
As far as I see in module mysql you have the feature called preparing queries.
So basically you should pass query and parameters for executing, f.e. your function definition will look like this function(query, parameters, callback), and than use mysql.format(query, parameters) before executing the query.

filter[0].ID is undefined

I am making a Discord Bot add a database entry when a new user joins. To avoid duplicate entries I'm checking if the database row ID already has the members ID in it. My problem is if the member is not in the database it comes back as undefined.
var userID = member.id.toString();
var UserName = member.user.username.toString();
// var NickName = member.nickname.toString();
var DateJoined = new Date();
con.query("SELECT ID FROM listAllUsers", function (err, selectResult, fields) {
var filter = selectResult.filter(m => m.ID === userID);
console.log(filter[0].ID)
if(filter[0].ID == userID) {
console.log(`That user all ready exists in the database.`)
} else {
var sql = `INSERT INTO listAllUsers (ID, UserName, NickName, DateJoined) VALUES ('${ID}', '${UserName}', 'none', '${DateJoined}')`;
con.query(sql, function (err, result) {
if (err) throw err;
console.log(`User: ${UserName} -- ${ID} has joined the server. Added to the Database`);
});
}
});
var filter = selectResult.filter(m => m.ID === userID);
This checks if the ID is equal to any of the ID's in the database. But this is also my problem. Because if this comes back empty it will make this:
console.log(filter[0].ID) undefined. Well actually the .ID bit comes back undefined.
Well if you have an entry, than you already know the id exists....
if (filter.length > 0) {
// you have a user with the id
}
But wouldn't it make more sense to just query the user id instead of returning everyone? SELECT ID FROM listAllUsers WHERE ID=userID

Node JS Loop Through Array Before Creating Property

I have a JSON input which contains data linking it to a secondary model (Users). I need to loop through listingData.Agents to get the index ID and then look up this index id to get the user. I push this to the user id to an array but due to the async the array is blank when the create property function is run. How you manipulate and get data from the array and then run the create once all your data is in place.
Thanks.
exports.createProperty = function(req,res,next) {
var listingData = req.body;
listingData.User = [];
_.forEach( listingData.Agents , function(n, key) {
User.findOne({ agentId : n.AgentId},function(err,user) {
listingData.User.push(user._id);
});
});
Property.create(listingData, function(err,property) {
if (err) {
res.status(400);
return res.send({reason:err.toString()});
}
res.send(req.property);
})}
If you don't mind introducing new library into your code, node-async could solve your problem.
Using node-async, you code would be:
var async = require('node-async')
exports.createProperty = function(req,res,next) {
var listingData = req.body;
listingData.User = [];
async.each(listingData.User,
function(n, key) {
User.findOne({ agentId : n.AgentId},function(err,user) {
listingData.User.push(user._id);
});
},
function (asyncErr){
//handle asyncErr first
Property.create(listingData, function(err,property) {
if (err) {
res.status(400);
return res.send({reason:err.toString()});
}
res.send(req.property);
});
});

Node/Express - How to wait until For Loop is over to respond with JSON

I have a function in my express app that makes multiple queries within a For Loop and I need to design a callback that responds with JSON when the loop is finished. But, I'm not sure how to do this in Node yet. Here is what I have so far, but it's not yet working...
exports.contacts_create = function(req, res) {
var contacts = req.body;
(function(res, contacts) {
for (var property in contacts) { // for each contact, save to db
if( !isNaN(property) ) {
contact = contacts[property];
var newContact = new Contact(contact);
newContact.user = req.user.id
newContact.save(function(err) {
if (err) { console.log(err) };
}); // .save
}; // if !isNAN
}; // for
self.response();
})(); // function
}; // contacts_create
exports.response = function(req, res, success) {
res.json('finished');
};
There are a few problems with your code besides just the callback structure.
var contacts = req.body;
(function(res, contacts) {
...
})(); // function
^ you are redefining contacts and res in the parameter list, but not passing in any arguments, so inside your function res and contacts will be undefined.
Also, not sure where your self variable is coming from, but maybe you defined that elsewhere.
As to the callback structure, you're looking for something like this (assuming contacts is an Array):
exports.contacts_create = function(req, res) {
var contacts = req.body;
var iterator = function (i) {
if (i >= contacts.length) {
res.json('finished'); // or call self.response() or whatever
return;
}
contact = contacts[i];
var newContact = new Contact(contact);
newContact.user = req.user.id
newContact.save(function(err) {
if (err)
console.log(err); //if this is really a failure, you should call response here and return
iterator(i + 1); //re-call this function with the next index
});
};
iterator(0); //start the async "for" loop
};
However, you may want to consider performing your database saves in parallel. Something like this:
var savesPending = contacts.length;
var saveCallback = function (i, err) {
if (err)
console.log('Saving contact ' + i + ' failed.');
if (--savesPending === 0)
res.json('finished');
};
for (var i in contacts) {
...
newContact.save(saveCallback.bind(null, i));
}
This way you don't have to wait for each save to complete before starting the next round-trip to the database.
If you're unfamiliar with why I used saveCallback.bind(null, i), it's basically so the callback can know which contact failed in the event of an error. See Function.prototype.bind if you need a reference.

Categories