Angular showing "Cannot read property 'friends' of null" - node.js

Hi I am trying trying to get data from my nodejs backend to angular. And i get the below error message in nodejs
Cannot read property 'friends' of null
at UserModel.findOne.select.lean.exec
The Api Works fine, if i try to use in postman. But when used in angular i get the error message in nodejs
The server side code is:
let findFriends = ()=>{
return new Promise((resolve, reject)=>{
UserModel.findOne({userId: req.body.userId || req.query.userId})
.select('-__v -_id -password')
.lean()
.exec((err, userFriends)=>{
console.log(userFriends.friends.length)
if(err){
logger.error(err.message, ' friendsController: getAllNonFriends, findFriends', 5)
let apiResponse = response.generate(true, `Failed to Find Friends`, 500, null)
reject(apiResponse)
}else {
if(userFriends.friends.length !== 0){
resolve(userFriends.friends)
}else {
resolve(userFriends)
}
}
})
})
} // end find requests
the code in angular:
public allNonFriends: any = ()=>{
this.http.getNonFriendsList(this.currentUser).subscribe(
(apiResponse)=>{
console.log(apiResponse)
if(apiResponse.status === 200){
console.log(apiResponse.data)
} else {
console.log(apiResponse.message)
}
},
(err)=>{
console.log(err)
}
)
} // end all non friends

I found the solution. I change the parameter from body to query and it worked

Related

HTTP: Industry standards for back responses to the client

Hi all I'm new to web development so I'm developing a simple online recipe book to allow me to also learn node and angular in the process.
How ever I'm struggling with what type of responses I should send back to the client for success and fails, in the case of post requests, or delete requests.
Here's an example of an api POST access point:
app.post('/recipe/',(req,res)=>{
res.set({
'Access-Control-Allow-Origin': 'http://localhost:4201'
})
console.log("Recieved req at /recipe/")
if(req.body.recipe === undefined){
res.send("Request not filled. No recipe found");
}
if(req.body.ingredients === undefined){
res.send("Request not filled. No ingredients found");
}
//var r = new Recipe(req.body.recipe,req.body.ingredients);
mongo.addRecipe(req.body.recipe,req.body.ingredients).then((promise)=>{
mongo.getAllRecipeByName().then(promise=>{
console.log(promise);
});
res.send(promise);
})
})
Here's the code for mongo.addRecipe() so you know what's being returned in that promise:
async addRecipe(recipeName,ingredients){
if(ingredients == null){
return null;
}
if(recipeName == null){
return null;
}
var recipe = new Recipe(recipeName,ingredients);
if(recipe.getIngredients().length <= 0){
return null;
}
try{
const client = new MongoClient(this.uriString);
await client.connect();
const db = client.db(this.databaseString);
const recipeCollection = db.collection(this.collectionString);
var status = await recipeCollection.insertOne(recipe);
client.close();
if(status.acknowledge == true){
return status
}
else{
return status
}
//console.log(await recipeCollection.find({recipeName:recipeName}).toArray());
}
catch(e){
console.error("Failed addRecipe() params: "+recipeName+" "+ingredients+e);
return null;
}
//String recipeName List<String> ingredients
//creates connection with mongo database.
//add {name:'recipeName',ingredients:'ingredients'} to mongoDB
}
So as you can see some of my verification statements return null and then I'm sending null back to the client. Is this a mistake? In the case of success I am returning the massive object that's returned from collection.insertOne();
What should I be sending to the client in the case of success and failure that fits with the industry standards?

Handling Multiple functionalities in Firebase using Nodejs

Hellow all,
I'm Newbie to Nodejs and Firebase, I need two functionalities to takes place in a single function and also I have written a piece of code it's works fine.
But My question is, the code I have written is the correct way to achieve the multiple functionality or do we have any other alternate method(correct way) to achieve the same functionality.
Doubt :
Retrieving relevant details of project ----> Inside Callback function ----> saving data to another table ----> Inside Callback function ----> Deleting data from table -----> Inside Callback function ----> response
Do we need to write the functionality inside the nested callback function to achieve the output or is there is any other way to achieve it .
// Nodejs Post Function
app.post('/delete_user_request_project/', function (req, res)
{
if (!is_admin_login(req.cookies.login_type))
{
return res.redirect('/');
}
var project_id = req.body.project_id; // Getting the project Id
let del_ref = admin.database().ref("user_request_project/" + project_id); // Targeting the details of the project to fetch that particular data
del_ref.once("value", function (snapshot)
{
var request_project_obj = snapshot.val(); // fetching the details of project
if (request_project_obj != null)
{
let update_ref = admin.database().ref("deleted_user_request_project/" + project_id);
update_ref.set(
request_project_obj // Updating project details to another table
).then(function ()
{
del_ref.remove().then(function () // Deleting the details from project Table
{
return res.status(200).send('success');
});
});
}
else
{
var error = "プロジェクトが存在しない";
req.flash("error", error_message);
return res.send({
status: 'error',
error: error
});
}
});
})
TIA
I would suggest you use the Promise version of the once() method instead of the Callback version, as follows. It will allow you to correctly chain the different promises returned by the asynchronous Firebase method.
app.post('/delete_user_request_project/', function (req, res) {
if (!is_admin_login(req.cookies.login_type)) {
return res.redirect('/');
}
var project_id = req.body.project_id; // Getting the project Id
let del_ref = admin.database().ref("user_request_project/" + project_id); // Targeting the details of the project to fetch that particular data
del_ref.once("value")
.then(function (snapshot) {
var request_project_obj = snapshot.val(); // fetching the details of project
if (request_project_obj != null) {
let update_ref = admin.database().ref("deleted_user_request_project/" + project_id);
return update_ref.set(request_project_obj); // Updating project details to another table
}
else {
throw new Error('request_project_obj null');
}
})
.then(function () {
return del_ref.remove();
})
.then(function () // Deleting the details from project Table
{
return res.status(200).send('success');
})
.catch(function (error) {
if (error.message === 'request_project_obj null') {
var error = "プロジェクトが存在しない";
req.flash("error", error_message);
return res.send({
status: 'error',
error: error
});
} else {
//...
}
})
})

How to reset global variable on every new HTTP POST request?

We are actually tring to read a csv file as input and throw out the corresponding results for the data in CSV file.
For every new http POST request, new result is being appended to the existing data in array(productDetails), but I want to flush the old data in array for every new request.
let productDetails=[];
router.get('/add-product',(req,res,next)=>{
res.sendFile(path.join(__dirname,'../','views','add-product.html'))
})
router.post('/add-product',(req,res,next)=>{
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
else {
var sampleFile=req.files.file;
sampleFile.mv('././uploads/'+sampleFile.name,function(err){
if(err){
return res.status(500).send(err);
}
})
readFile('././uploads/'+sampleFile.name,'utf-8',(err,fileContent)=>{
if(err){
console.log(err); // Do something to handle the error or just throw it
throw new Error(err);
}
const jsonObj = csvjson.toObject(fileContent);
jsonObj.forEach(obj=>{
data.forEach(obj1=>{
if(obj.Make ==obj1.Make && obj.Manufacture == obj1.Manufacture && obj.Product==obj1.Product){
productDetails.push({
product:obj1.Product,
price:obj1.Price,
manufacture:obj1.Manufacture,
make:obj1.Make
})
}
})
})
})
}
res.redirect('/');
})
exports.routes=router;
exports.productDetails=productDetails;
You Can try by adding this line
router.post('/add-product',(req,res,next)=>{
productDetails=[];
//YOUR CODE
})
I think you need a function variable rather than a global variable for producrDetails, so if you define your variable inside the POST call it will work according to your requirements and start will an empty productDetails array on every POST call.
router.post('/add-product',(req,res,next)=>{
let productDetails=[]
// CODE
jsonObj.forEach(obj=>{
data.forEach(obj1=>{
if(obj.Make ==obj1.Make && obj.Manufacture == obj1.Manufacture && obj.Product==obj1.Product){
productDetails.push({
product:obj1.Product,
price:obj1.Price,
manufacture:obj1.Manufacture,
make:obj1.Make
})
}
})
})
}

handling 'res' in Node JS

I am relatively new to NodeJS and have run into an issue. Incoming request from Angluar UI has two parameters (loginId and password) and on Node, I am reading the data from a local json file, iterating through the 'users' array and based on the matching params, I am sending the particular object in the server response. However, my logic is failing where there are multiple objects in the 'users' array and I have to send a server response for the not-matched one as well. I know that I cannot send multiple responses but that is where i need the help. Any help will be highly appreciated.
Here is the code:
if (jsonData.users.length > 0) {
jsonData.users.forEach(user => {
if ((reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password) {
res.send({ 'userData': user });
} else {
res.json({ 'userData': 'No records found' });
}
})
res.send ends the response.
So using it a second time it will not send anything.
https://www.nodejsconnect.com/blog/articles/sending-multiple-http-responses-expressjs
EDIT:
I'm not completely sure what you want, but I think you want to do something like this.
-> return the user for whom the userId and password matches or return 'no records found' ( or even better send an 401 - unauthorized - status code)
const user = jsonData.users.find(user => (reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password));
if (user) {
res.send({ 'userData': user });
} else {
res.json({ 'userData': 'No records found' });
// or res.sendStatus(401); // unauth
}
Try this... If you wanna break the loop after a match.
if (jsonData.users.length > 0) {
let isMatch = false;
jsonData.users.forEach(user => {
if ((reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password) {
isMatch = true;
return res.send({ 'userData': user });
}
})
if(!isMatch)
res.json({ 'userData': 'No records found' });
}

NodeJs promises returning too early

I'm new to NodeJs and code I'm working with is using Q framework for promises.
And it seems that I don't understand the 'Q' framework too well, I'm running into a case when promises are returning too early.
Here is my code:
BridgeInfo.getBridgeInfo(exten)
.then(function processBridgeInfo(bridge_info) {
console.log("Nitesh -- bridge info is back, yay");
if (bridge_info !== undefined) {
conf_bridge = new VoxConfBridge(ari);
conf_bridge.init(bridge_info);
/**Add the bridge to the bridgeList**/
bridgeList[conf_bridge.bridge.id] = conf_bridge;
console.log("Bridge ID to register is "+ conf_bridge.bridge.id);
self.registerEvents(conf_bridge.bridge);
conf_bridge.registerUser(event, false, channel);
} else {
console.log("Unknown extension [" + exten + "] blocking it");
ChannelDriver.blockChannel(ari, channel.id);
}
})
.catch(function handleError(err) {
console.error("Nitesh -- [voxbridgemanager] error occured "+err);
});
The above code calls a function getBridgeInfo, this function is supposed to do some DB queries and return the result.
Here is the code in getBridgeInfo
BridgeInfo.getBridgeInfo = Q.async(function(bridge_identifier) {
console.log("Nitesh -- Getting the bridge info for ["+ bridge_identifier + "]");
if (bridge_identifier !== undefined) {
db.getConfBridgeProfile(bridge_identifier)
.then(function processBridgeProfile(result) {
if (result !== undefined) {
console.log("Nitesh -- Bridge Info is "+ JSON.stringify(result));
var bridge_info = new BridgeInfo();
bridge_info.init(result)
.then (function bridgeInfoInitDone() {
return bridge_info;
})
.catch( function handleError(err) {
console.error("Nitesh ---[bridgeInfoInit] Error is "+ err);
});
}
else {
console.log("Can't find any bridge profile for this identifier ["+ bridge_identifier + "]");
}
}, function handleError(err) {
console.error("Failed to retrieve bridgeInfo");
});
} else {
console.error("Received an invalid identifier");
}
});
**When I run this code, I see that in my main code,which calls getBrigeInfo, it hits its catch error handler even before getBRidgeInfo has executed completely, getBridgeInfo's SQL query results appear afterwards.
I think the way I'm using promises isn't being done correctly, any explanations please
Your missing the key part of what promises can do.
You should not need to do any catch statements in your getBridgeInfo. You should return the whole promise that gets the SQL data... and handle it in your first block of code BridgeInfo.getBridgeInfo(exten)
Assuming that db.getConfBridgeProfile(bridge_identifier); returns a promise
Example:
BridgeInfo.getBridgeInfo = function(bridge_identifier) {
console.log("Nitesh -- Getting the bridge info for ["+ bridge_identifier + "]");
if (bridge_identifier !== undefined) {
return Q.fcall(function () {
throw new Error("Received an invalid identifier");
});
}
return db.getConfBridgeProfile(bridge_identifier);
}
I've also seperated out your process query... keep things simple.
BridgeInfo.processBridgeProfile = function(result) {
if (result !== undefined) {
console.log("Nitesh -- Bridge Info is "+ JSON.stringify(result));
var bridge_info = new BridgeInfo();
return bridge_info.init(result);
}else{
return Q.fcall(function () {
throw new Error("Can't find any bridge profile for this identifier ["+ bridge_identifier + "]");
});
}
Return promises and handle the catch in the main function. Your getting stuck in handling a catch, the SQL results are not getting returned like they should.
Call:
BridgeInfo.getBridgeInfo(bridge_identifier).then(function(result){
return BridgeInfo.processBridgeProfile(result)
}).then(function(){
//Do the rest here
}).catch(function(){
//One catch to rule them all :)
});

Resources