I am trying to send an object from nodejs server to the front end but one property is keep getting deleted on the way
server
router.post('/cart/retrieve', (req, res) => {
let cart = req.session.cart;
let prodId = Object.keys(cart);
Product.find({_id: {$in: prodId}}, (err, result) => {
if (err) throw err;
let resultToSend = [];
for (let i = 0; i < result.length; i++) {
let curResult = result[i];
curResult['cartQuantity'] = parseInt(cart[curResult._id]);
result[i] = curResult;
}
resultToSend = result;
console.log(resultToSend[0]['cartQuantity'])
res.json({cart: resultToSend})
});
});
frontend
$("#top-cart-trigger").click(function(e){
$.post('/api/shop/cart/retrieve',{
}, function (returnResult) {
console.log(returnResult['cart'][0]['cartQuantity'])
let products = returnResult['cart'];
console.log(returnResult)
for(let i = 0; i < products.length; i ++){
let curProduct = products[i];
console.log(curProduct['cartQuantity'])
}
});
});
so practically the json variable sent from server and the returnResult received from the front end are same variables. However, my console.log(resultToSend[0]['cartQuantity']) returns 3 (which is correct) but console.log(curProduct['cartQuantity']) is undefined for all elements. What am I doing wrong?
I think the problem might comes from mutable variable result in your server.
However it seems like the variable returnResult['cart'] is JSON and you are expecting array. You could use 'for in' instead. See https://developer.mozilla.org/cs/docs/Web/JavaScript/Reference/Statements/for...in
Just try to replace for loop with this
for (let key in returnResult['cart']){
console.log(returnResult['cart'][key]['cartQuantity']);
}
Related
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 beginner in express js, i made api for my music app from express and firebase, that takes data from firebase and takes request and send data as response. But there is problem which is messing the program. Each time the value (Views of music) of firebase changes it re sends the same response.
heres my code
app.use(cors())
let trendingTracks = []
let data;
function Trending(data){
if (data){
Object.values(data).forEach((value)=>{
if(value.views < 10){
trendingTracks.push(value)
}
})
}
}
function SortPopular(a){
for(let i = 0; i<=a.length; i++){
for (let j = i+1; j<a.length; j++){
if(a[i].views>a[j].views){
const temp = a[i]
a[i]=a[j]
a[j]=temp
}
}
}
return a
}
firebase.database().ref("public/songs").on("value", snapshot =>{
data = snapshot.val();
Trending(data)
})
app.get("/api/home/trending", (req, res)=>{
res.send(SortPopular(trendingTracks))
})
app.listen(4000, ()=>console.log("listening at port 4000..."))
This is what my database looks like:
And each time views value changes it re response the same data.
When the value of database is not changed:
When the value of database is changed:
As you can see the same thing re sends.
I do not see your whole code, so I cannot be 100% sure, but I suspect it happens because you are constantly adding items to trendingTracks, but need to actually clear it every time you run Trending function.
So add trendingTracks = [] as in here:
app.use(cors())
let trendingTracks = []
let data;
function Trending(data){
if (data){
trendingTracks = [] // NEW
Object.values(data).forEach((value)=>{
if(value.views < 10){
trendingTracks.push(value)
}
})
}
}
function SortPopular(a){
for(let i = 0; i<=a.length; i++){
for (let j = i+1; j<a.length; j++){
if(a[i].views>a[j].views){
const temp = a[i]
a[i]=a[j]
a[j]=temp
}
}
}
return a
}
firebase.database().ref("public/songs").on("value", snapshot =>{
data = snapshot.val();
Trending(data)
})
app.get("/api/home/trending", (req, res)=>{
res.send(SortPopular(trendingTracks))
})
I've been scouring similar problems but haven't seem to have found a solution that quite works on my end. So I'm working on a Discord bot that takes data from a MongoDB database and displays said data in the form of a discord embedded message using Mongoose. For the most part, everything is working fine, however one little section of my code is giving me trouble.
So I need to import an array of both all available users and the "time" data of each of those users. Here is the block of code I use to import said data:
for (i = 0;i < totalObj; i++){
timeArray[i] = await getData('time', i);
userArray[i] = await getData('user', i);
}
Now this for loop references a function I made called getData which obtains the data from MongoDB by this method:
async function getData(field, value){
var data;
await stats.find({}, function(err, result){
if(err){
result.send(err);
}else{
data = result[value];
}
});
if(field == "user"){
return data.user;
}else if (field == "time"){
return data.time;
}else{
return 0;
}
So that for loop is where my errors currently lie. When I try to run this code and display my data through a discord message, I get this error and the message does not get sent:
(node:13936) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'time' of undefined
Now the strange thing is, this error does not happen every time. If I continue calling the command that triggers this code from my discord server, it's almost like a 50/50 shot if the command actually shows the message or instead gives this error. It is very inconsistent.
This error is confounding me, as the undefined part does not make sense to me. The objects that are being searched for in the mongoDB collection are definitely defined, and the for loop never exceeds the number of objects present. My only conclusion is that I'm doing something wrong with my asynchronous function design. I have tried altering code to use the getData function less often, or to not use awaits or asynchronous design at all, however this leaves my final discord message with several undefined variables and an eventual crash.
If anyone has any advice or suggestions, that would be very much appreciated. Just for reference, here is the full function that receives the data, sorts it, and prepares a string to be displayed on the discord server (though the error only seems to occur in the first for loop):
async function buildString(){
var string = "";
var totalObj;
var timeArray = [];
var userArray = [];
var stopSort = false;
await stats.find({}, function(err, result){
if(err){
result.send(err);
}else{
totalObj = result.length;
}
});
for (i = 0;i < totalObj; i++){
timeArray[i] = await getData('time', i);
userArray[i] = await getData('user', i);
}
while(!stopSort){
var keepSorting = false;
for(i = 0; i < totalObj ; i++){
var target = await convertTime(timeArray[i]);
for(j = i + 1 ; j < totalObj ; j++){
var comparison = await convertTime(timeArray[j]);
if(target > comparison){
//Switch target time with comparison time so that the lower time is up front
var temp = timeArray[i];
timeArray[i] = timeArray[j];
timeArray[j] = temp;
//Then switch the users around so that the user always corresponds with their time
var userTemp = userArray[i];
userArray[i] = userArray[j];
userArray[j] = userTemp;
//The loop will continue if even a single switch is made
keepSorting = true;
}
}
}
if(!keepSorting){
stopSort = true;
}
}
//String building starts here
var placeArray = [':first_place: **1st', ':second_place: **2nd', ':third_place: **3rd', '**4th', '**5th', '**6th', '**7th', '**8th', '**9th', '**10th'];
for(i = 0; i < totalObj; i++){
string = await string.concat(placeArray[i] + ": " + userArray[i] + "** - " + timeArray[i] + " \n\n");
console.log('butt');
}
console.log("This String:" + string);
return string;
}
I think problem is you are trying to await function with callback, it will not work => access to data.time may run before data = result[value]. If you need await callback, you can use custom Promise (or use util.promisify, more info here)
Promise:
function findStats(options) {
return new Promise((resolve, reject) => {
return stats.find(options, function (err, result) {
if (err) {
return reject(err)
}
return resolve(result)
})
})
}
utils.promisify
const util = require('util');
const findStats = util.promisify(stats.find);
Now you can use await in your function
async function getData(field, value) {
try {
const result = await findStats({})
const data = result.value
if (field === 'user') {
return data.user
}
if (field === 'time') {
return data.time
}
return 0
} catch (error) {
// here process error the way you like
// or remove try-catch block and sanitize error in your wrap function
}
}
Sorry if this is a stupid question, but how would I go about adding items into a list? So what I've got is a loop that basically runs through and tries to convert all the urls to tinyurls from a web scraper . It still produces an empty list for images_short. I'm not very familiar with nodejs's syntax. Here's a snippet of code, I've put some data in the images_long list:
const TinyURL = require('tinyurl');
var images_long = ['https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d', 'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
var images_short = [];
for (i = 0; i < 2; i++) {
TinyURL.shorten(images_long[i], function(res) {
images_short.push(res[i]);
});
}
I still get an empty list when I changed images_short.push(res[i]); to images_short.push(res);
res is a string, so just images_short.push(res); will do the trick. Also, you should iterate with respect to the length of the variable you're indexing, and you should var your indexing variable (i):
const TinyURL = require('tinyurl');
var images_long = [
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d',
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
var images_short = [];
for (var i = 0; i < images_long.length; i++) {
TinyURL.shorten(images_long[i], function(res) {
images_short.push(res);
});
}
The tinyurl library is async.
Is we use native map, the resulting callback wouldn't be returned if we try to console.log(images_short) until all the links in the array have been shortened.
We can however, use async and specificically use async.map to return the results like the example below.
const TinyURL = require('tinyurl');
const async = require('async');
var images_long = [
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d',
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
function shorten(item, cb) {
TinyURL.shorten(item, function(res) {
cb(null, res);
});
}
async.map(images_long, shorten, (err, results) => {
console.log(results);
});
we can assign images_short if you want to keep consistency.
I'm working on a personal project and I'm stump in the last part. I'm trying to only get the data for companies that have the same name of the companies in my database.
My goal at the end is to merge the two jsons obtained from the two following calls into one
Call one: $http.get('//localhost:8081/api/jobs').then(function(res)
Call two: localhost:8081/api/glassdoor/
Full Code:
$http.get('//localhost:8081/api/jobs').then(function(res) {
$scope.data = res.data; //data from the database
$scope.size = $scope.data.length; //length 132
for (var i = 0; i < $scope.size; i++) {
if ($scope.data[i].glassdoor !== null && $scope.data[i].glassdoor !== undefined) {
$scope.hasGlassdoor = [];
for (var i = 0; i < $scope.size; i++) {
if ($scope.data[i].glassdoor !== null && $scope.data[i].glassdoor !== undefined)
$scope.hasGlassdoor.push($scope.data[i]);
}
//Get the companies name that have glassdoor
$scope.company = [];
for (var j = 0; j < $scope.hasGlassdoor.length; j++) {
$scope.company.push($scope.hasGlassdoor[j].company);
}
//Create the URL calls for my glassdoor api
$scope.url = [];
for (var x = 0; x < $scope.company.length; x++) {
$scope.url.push('//localhost:8081/api/glassdoor/' + $scope.company[x]);
}
//For example : '//localhost:8081/api/glassdoor/A9.com'
//Get the Glassdoor data
var company = $scope.company;
for (var j = 0; j < $scope.url.length; j++) {
$http.get($scope.url[j]).then(function(response) {
$scope.gData = response.data;
$scope.gSize = $scope.gData.length;
$scope.gName = [];
//Get the names of the companies that glassdoor returns
for(var x = 0; x < $scope.gSize; x++){
if ($scope.gData[x] !== null && $scope.gData[x] !== undefined) {
if ($scope.gData[x].name !== null && $scope.gData[x].name !== undefined) {
$scope.gName.push($scope.gData[x].name);
}
}
}
//Now I'm trying to only get the names of the companies that are in my variable company
//For example '//localhost:8081/api/glassdoor/6sense
//returns data for 6sense, and a company named 6sense Technologies
//I'm trying to just get the data of 6sense
//
// TODO
//
// My try using loDash returns undefined.
// I'm trying to see if $scope.gName is in var Company.
//if(_.includes(company, $scope.gName)){
// gd.push($scope.gName);
//}
}); //this is what is calling the glassdoor api
}//end of the for loop for url.
} //if statement to check for null
} //first for loop
}).catch(function(error, res) {
console.log("Error:", error, res);
});
Right now I'm working on small list so I can fix this issue.
My goal at the end is to have this as my finished json:
[
{
"company": "23andMe"
"glassdoor":"https://www.glassdoor.com/Overview/Working-at-23andMe-EI_IE145899.11,18.htm"
"img":"https://www.23andme.com/static/img/icons/logo_alt.96cf7888b73d.svg"
"international":null
"link":"https://www.23andme.com/careers/"
"location":"Mountain View, CA"
"secondary":null
"third":null
"id":145899,
"name":"23andMe",
"website":"www.23andme.com",
"isEEP":true,
"exactMatch":true,
"industry":"Biotech & Pharmaceuticals",
"numberOfRatings":27,
"squareLogo":"https://media.glassdoor.com/sqll/145899/23andme-squarelogo.png",
"overallRating":"4.2",
"ratingDescription":"Very Satisfied",
"cultureAndValuesRating":"4.5",
"seniorLeadershipRating":"3.6",
"compensationAndBenefitsRating":"4.0",
"careerOpportunitiesRating":"3.4",
"workLifeBalanceRating":"4.3",
"recommendToFriendRating":80,
"sectorId":10005,
"sectorName":"Biotech & Pharmaceuticals",
"industryId":200021,
"industryName":"Biotech & Pharmaceuticals",
"featuredReview":{
"attributionURL":"https://www.glassdoor.com/Reviews/Employee-Review-23andMe-RVW11447587.htm",
"id":11447587,
"currentJob":true,
"reviewDateTime":"2016-08-03 15:05:20.157",
"jobTitle":"Customer Care Reporesentative",
"location":"Mountain View, CA",
"jobTitleFromDb":"Customer Care Reporesentative",
"headline":"Customer Care Representative",
"pros":"the environment-everyone is extremely genuine, smart, and friendly. management is very understanding and open. Executives are transparent with everything going on in the company\r\nbenefits-free gym, food every day, snacks, great health coverage, rooftop access, etc\r\nworkspace-facilities does a phenomenal job at keeping everything extremely clean and fixes all issues ASAP. I don't feel like I'm sitting a boring desk job all day, it's a fun place to be",
"cons":"Traffic through downtown mountain view can suck and the train can be kind of loud (I cannot think of a legitimate con, everything is awesome here)",
"overall":5,
"overallNumeric":5
},
"ceo":{
"name":"Anne Wojcicki",
"title":"CEO",
"numberOfRatings":15,
"pctApprove":100,
"pctDisapprove":0
}
}
]
Server.js that deals with the glassdoor call:
//Glassdoor api call
app.get('/api/glassdoor/:company', function(req, res, next) {
var company = req.params.company;
requestify.get('https://api.glassdoor.com/api/api.htm?t.p=PRODUCT&t.k=KEY&userip=0.0.0.0&useragent=&format=json&v=1&action=employers&q=' + company).then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
gData = response.getBody();
gData = gData.response.employers;
res.json(gData);
});
});
Sort the array, then enumerate it. If previous === current you have a dupe.
This is how I solved it.
app.get('/api/glassdoor/:company', function(req, res, next) {
var company = req.params.company;
requestify.get('https://api.glassdoor.com/api/api.htm?t.p=PRODUCT&t.k=KEY&userip=0.0.0.0&useragent=&format=json&v=1&action=employers&q=' + company).then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
gData = response.getBody();
gData = gData.response.employers;
//What I added to only send the data of the companies that where like 'company'
for (var i = 0; i < gData.length; i++) {
if (gData[i].name === company) {
gData = gData[i];
res.send(gData);
}
}
});
});
Which doesn't answer the overall question but that is how I solved my particular issue.