res.render() calls promise twice expressjs - node.js

Hello I am still a beginner in Nodejs and MongoDB. When I am running res.render() function as shown below I get 2 console logs, first with the correct result from mongodb find query and second with null. If I remove res.render() It works properly with only one console.log() output and not the second null.
router.get('/:areaslug', (req, res) => {
// Query results
let areavar = {}
return client.db("AwesomeApartments")
.collection("areas")
.findOne({slug: req.params.areaslug
})
.then((datadb) => {
// first time shows correct results next it shows null
console.log(" bug-testing : "+JSON.stringify(datadb));
//storing result of first query to my object
areavar = datadb;
return client.db("AwesomeApartments")
.collection("apartments")
.find({area:datadb._id})
.toArray()
})
.then((apartmentdb) => {
// Storing results of second query
areavar.apartments = apartmentdb;
//removing this solves the issue
return res.render('area',areavar);
}).catch(err =>
{
console.log(err);
return;
})
});

To those who find their way here, browser was generating two get requests. First one for query and second one for favicon.ico. Handling favicon.ico request solved this issue.

Related

node-postgres why is req.query.record empty?

When I start my nodejs app (with dust) on localhost:3000 the following code is used to grab all rows from my products tables (postgres db) and display them on my index page. It seemed to work fine last week.
app.get('/', async (req, res) => {
var parms = req.query.record;
const results = await pool.query('SELECT * FROM products WHERE id = $1',[parms], function (err, result) {
if (err) {
return console.error('error running query', err);
}
res.render('index', { products: result.rows });
});
});
For some reason now "req.query.record" is empty "[ ]" so no results are displayed on my index page.
If I navigate to localhost:3000/?record=3 it works fine and I can see the one record on my index page.
Also, if I edit the "results" in the original code and change [parms] to [3] then it works fine as well and displays that one record on my index page.
what would cause var parms = req.query.record; to return an empty object? Is that the expected behavior?
Okay, I think I have it. Bergi (it is the request) is correct and it was the expected behavior. I started the code from a tutorial posted before July 2017. the original pg.connect was hard deprecated. pg.connect not a function?
As a result I started hacking together something with the new pg.Pool(...).connect(...). The method described in my original question must have gotten mushed up with something else. As far as I know there is no need to process any query string from the index page when I am trying to return all rows from a table.
There is nothing after http://localhost:3000 which is why the result was an empty object. that is the expected behavior. http://localhost:3000/?record=3 did return the one row because req.query.record picked out [3] from the query string which is the expected behavior. The method in the original question would be used for returning one row from the table when the id is passed in the query string.
for my purposes, returning all rows, I replaced my app.get with...
app.get('/', async (req, res) => {
await pool.query('SELECT * FROM library', function (err, result) {
if (err) {
return console.error('error running query', err);
}
res.render('index', { recipes: result.rows });
});
});
If I wanted to use both methods I guess I would first run a check to see if there is a query string then proceed with the original app.get if true. else run the second app.get method to get all rows.
I just started with NodeJS and Postgres but am not sure why I didn't notice that from the get-go. Not sure if this will be a useful question/answer for anyone but I'll leave it up.

NodeJS Express: how to get object item

I try to create a simple login form and fail to validate the password from the MongoDB.
First I create the .post route for the form validation and then I get the MongoDB data which I want to compare with the form.
Here is my code:
app.post('/users', (req, res) => {
const reqUser = req.body.params.name
const reqPW = req.body.params.password
// connect to mongoDB
const collection = client.db().collection("users")
collection.find({name: reqUser}).toArray(function (err, results) {
if (err) {
console.log(err)
res.send([])
return
}
else {
console.log('RESULT', results) // returns the object
console.log('RES PW', results.password) // returns undefined
// this does not work
Object.keys(results).forEach(function(key) {
console.log('key is: ', key); // returns 0
});
// validate user+pw
if (!reqUser || !reqPW/*|| reqPW !== password*/) {
return res.status(401).end()
}
// send result to frontend
res.send(results)
res.end
}
})
})
So, I get my object returned in results but I cannot get the data from the object.
I also tried to convert it to an array with Array.from() but that didn't work either.
Please note that I did not yet implement hashing and salting the passwords yet, as I thought I want a working validation first. Do I need to implement those first?
I just checked the doc:
The toArray() method returns an array that contains all the documents from a cursor. The method iterates completely the cursor, loading all the documents into RAM and exhausting the cursor.
So toArray() will return a array, not object, therefore your results will be an array containing all the items(object) you get from the db. If you console.log(results), it should print an array rather than object.
Assuming there won't be two users have the same name, the results you get will be just an array containing one object, so you can just do:
results[0].password // get the first object's password field
Not sure if this slove your question, but based on your code thats the problem i found in it.

How to execute get after post in nodejs?

I'm executing post from react and after that I have some calculations on my back end. How to execute get to show the result on my front end after post and calculation ?
I think I got your question, albeit vague.
But,
1) You want to post a data to some route. The route maybe gives a success response or an error or maybe some different data, but it internally does some processing maybe adds some row to a db table.
2) You want to fetch the current state of the db table(I am assuming table, may be anything).
If this is the scenario, you can do what you are doing just add a get call in the chain.
axios.post('/api/OddsCalculator', newGame)
.then(games => {
// this means you got your game
this.setState({ games }, () => console.log(), games);
//now add one get request as well
return axios('/api/getSomeData');
})
.then((data)=>{
//this data is from the GET call
this.setState({ data })
})
.catch(err => this.setState({
errors: err.response.data
}))
Hope this is a fair assumption, but feel free to edit the answer when you get your solution.
Refer Promise Chaining here: https://javascript.info/promise-chaining
You call it on the success of the previous method. You use nested calls. Please find below example where there should be two methods : yourPostMethod & yourGetMethod defined before you call them.
function handler () {
return yourPostMethod()
.then(yourGetMethod)
.then((result) => {
console.log(result)
return result
})
}
You have express tag in question, so I am assuming you're using that.
With express, redirect works beautifully. I use it all the time
Say:
app.post('/somePOSTpath', (req, res) => {
// Do Some stuff
res.redirect('/somepath');
})
This will direct your backend to somepath at the end.

Node.js DNS Lookup scope error? (POST request)

I'm making a DNS Lookup API using Node.js and Express.js framework such that when it sends a POST request, it should return the addresses of different record types.
app.post('/', (req, res) => {
// Request format
// const l = {
// lookup: 'twitter.com',
// recordTypes: ['A', 'TXT']
// };
// Using destructor to fetch properties
const { lookup, recordTypes } = req.body;
console.log(lookup, recordTypes);
// For each record type
recordTypes.forEach(function(type) {
// setTimeout to get something async
setTimeout(function() {
dns.resolve(lookup.toLowerCase(), type, (err, addresses) => {
console.log(type);
if (err) {
return console.log(`\nType(${type}):\n`, err);
}
result = result + JSON.stringify({ type: `${type}`, response: { addresses } });
console.log(result);
});
}, 2000);
});
res.send(result);
});
It logs the correct stuff in the console but when it comes to the response, it returns an empty string. I used setTimeout to mimic the asynchronous nature of the request but it just does not work.
Please assume that I have declared stuff like result etc. because it is working. Also, please don't to redirect me to the Node.js documentation because I have already read that stuff and that's not the problem here. The problem is that I need to get every record type in an array and send that back as a response.
Here's what I have tried:
Tried to push response for each record type in the result array,
Tried to use a for of loop instead of forEach
Please help!
The way I'm reading your code is that for each item in the array you correctly use callbacks to do each individual bit of processing.
However, remember that forEach itself is not asynchronous. Thus you are setting up a bunch of tasks that will complete sometime, then returning undefined... then your results start to trickle in.
There's a couple ways to correctly. As you are using callbacks here I will use that style. You want to get a callback when all items in an array have been completely processed. The async module does this very well, providing a lot of high quality methods that act on arrays and such and give you a way to have a callback when they are all over.
Your function will look something like:
let res = []
async.each( recordTypes,
( type, done ) => {
dns.resolve(lookup.toLowerCase(), type, (err, addresses) => {
result = result + JSON.stringify({ type: `${type}`, response: { addresses } });
done(err)
} )
},
(allOverError) => {
res.send(result);
}
)
Notice there are two function parameters here: the first one is called for every item in the list, and the last is called when every item in the list has been completely processed.
There are other ways too, promises or the async/await keywords (confusing because of the name of the async module), but callbacks are good.

Tile38 Near by query node call back function is not working

I'm building a small GEO application and it's using http://tile38.com/ and https://www.npmjs.com/package/tile38 node module. Everything working fine but I'm unable to get result from the NEARBY query from the node module. It looks like the call back function isn't working, I've spent lot of time but couldn't find a way out. What I want is get the result from the nearby query and assign to a variable.
Here is the code:
var Tile38 = require('tile38');
var client = new Tile38({host: 'localhost', port: 9851, debug: true });
// set a simple lat/lng coordinate
client.set('fleet', 'truck1', [33.5123, -112.2693])
// set with additional fields
client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000).execute((err, results) => {
console.log("########");
// this callback will be called multiple times
if (err) {
console.error("something went wrong! " + err);
} else {
console.log(results + "##########");
}
});;
but when I try the following simple query it's working fine.
client.get('fleet', 'truck1').then(data => {
console.log(data); // prints coordinates in geoJSON format
}).catch(err => {
console.log(err); // id not found
});
ALSO when I try the RAW query in the tile38-cli it's working fine.
NEARBY fleet POINT 33.5123 -112.2693 6000
Any help would appreciated.
Thanks in advance.
EDIT
I tried the following also but didn't work.
let query = client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000)
query.execute(function(results).then(results => {
console.dir(results); // results is an object.
}))
Receiving following error
query.execute(function(results).then(results => {
^
SyntaxError: Unexpected token .
the author of the node library for Tile38 here. Sorry for the trouble getting this working. I noticed a typo in the readme which may have thrown you off. I will correct this.
The execute() method returns a Promise, and (as you already figured out) the example should have stated
query.execute().then(results => {
console.dir(results);
});
instead of
query.execute(function(results).then(results => {
console.dir(results);
});
After long time debugging I found that following code is working:
let query = client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000)
query.execute().then(data => {
console.dir(results); // results is an object.
}))

Resources