Nodejs page not loading when rendering - javascript

I am using Nodejs and Mongoose. When I render the page nothing happens, the page just attempts to load. When I write to the console i can view all the entries in the collection (Kp). Please assist, as to what is wrong in my code.
router.get('/list', (req, res) => {
const arrayT = [];
Kp.find({})
.then(element => {
arrayT.forEach(function (element) {
arrayT.push({
summary: element.summary,
detailDesc: element.detailDesc
});
res.render('list', { arrayT });
})
})
.catch(err => console.log(err));
});

Your arrayT.forEach isn't iterating over anything since arrayT is empty and because it doesn't iterate over anything the res.render() line of code isn't ever hit. You could prove this with console.log();
My advice to you is to utilize async await and avoid promises as they can potentially lead to nested code like callbacks.
Preferred code:
router.get('/list', async (req, res) => {
try {
const arrayT = [];
const listOfKPs = await Kp.find({})
listOfKPs.forEach( ele => {
arrayT.push({
summary: element.summary,
detailDesc: element.detailDesc
});
});
return res.render('list', { arrayT });
}
catch(err) {
console.log(err);
return res.render('list', { [] }); // render empty list
}
});

Solution to my problem
router.get('/list', async (req, res) => {
try {
const list = await Kp.find({}).select('summary detailDesc -_id');
list.forEach(function(element){});
res.render('list', {list});
}
catch (err) {
res.json({ message: 'Test is not working ' + err });
console.log(err);
}
});
Thank you all for assisting with comments and answers.

Related

Redis get function

I'm getting github repo data, and then i store it in redis with set. with get am getting current data, but when i trying add function to get it's not working.
let redisClient;
(async () => {
redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
redisClient.on("connect", function () {
console.log("Redis Connected!");
});
await redisClient.connect();
})();
// Make request to Github for data
async function getRepos(req, res, next) {
try {
console.log("Fetching Data...");
const { username } = req.params;
// with this am getting result
const cacheResults = await redisClient.get(username);
console.log(cacheResults);
// with this am not getting result, how can i fix this?
redisClient.get(username, (err, data) => {
console.log(data);
});
const response = await fetch(`https://api.github.com/users/${username}`);
const data = await response.json();
const repos = data.public_repos;
// Set data to Redis
redisClient.set(username, JSON.stringify(repos));
res.send(setResponse(username, repos));
} catch (e) {
console.log(e);
res.status(500);
}
}
it's don't console.log(data), i searched a lot and everyone have one example how to use get function, but in me case it's don't log, whats am doing wrong?
this is my cache function
// Cache middleware
async function cache(req, res, next) {
const { username } = req.params;
try {
await redisClient.get(username).then((data) => {
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
} catch (error) {
console.log(error.toString());
}
}
app.get("/repos/:username", cache, getRepos);
it's works, but time finish times with cache and without it are same? am doing something wrong?
can you try like this
redisClient.get(username).then((data) => {
console.log(data);
});

Using async and await to handle queries

Having issues with using async and await. I'm executing two queries and then saving the result to a temp variable. After I have collected the response from all executed queries, I'm going to send that to the client.
Here is my current example code.
module.exports = (app) => {
app.get('/api/stats', (req, res) => {
let fetch1 = '';
let fetch2 = '';
conn.query('query here', [], async (error, results) => {
if (error) {
return res.send({
success: false,
message: 'There was an error.'
});
} else {
fetch1 = results;
}
});
conn.query('query here', [], async (error, results) => {
if (error) {
return res.send({
success: false,
message: 'There was an error.'
});
} else {
fetch2 = results;
}
});
// I need to wait until the queries have resolved so that I can send the correct data
return res.send({
success: true,
fetch1: fetch1,
fetch2: fetch2
});
});
};
I basically need to wait until the queries have been resolved so that I can send the correct data towards the end.
Can anyone explain how I can use await and async to accomplish this?
Thanks.
You can only await a Promise, so for functions that don't return Promises you need to create a Promise wrapper. This needs to be done per call that would previously use a callback, but you can make a helper function per function you need to wrap.
function queryPromise(query, parameters) {
return new Promise((resolve, reject) => {
conn.query(query, parameters, (err, results) => {
if(err) {
reject(err);
} else {
resolve(results);
}
});
});
}
module.exports = (app) => {
app.get('/api/stats', async (req, res) => {
try {
let fetch1 = await queryPromise('query here', []);
let fetch2 = await queryPromise('query here', []);
res.send({
success: true,
fetch1: fetch1,
fetch2: fetch2
});
} catch {
res.send({
success: false,
message: 'There was an error.'
});
}
});
};
From my knowledge, I usually apply async to functions and perform await on certain variables (inside the function) that need to be acquired from a specific database.
So to implement this into your function containing the async tag, you could possibly do:
fetch1 = await results;
fetch2 = await results;
This will wait until the data is attached onto the variable fetch1 and fetch2 before continuing on with the code.
Sorry if this was very vague, hopefully this was somewhat helpful.

How to work with Async/Await in expressjs router?

I've been battling with an issue concerning Async/Await, I'm relatively new to Nodejs. I have a repository where I connect directly to my mongodb collection to retrieve some data it but when I connect my controller to this repository, I get a nulled response.
Please checkout my code below:-
SyncRepository.js
const mongoose = require('mongoose');
exports.ItemRepo = async (limit) => {
try {
await mongoose.connection.db.collection('items_1087342')
.find({}, {timeout: false}).limit(limit).toArray((err, results) => {
// results.forEach(e => {
// console.log(e.item_id);
// }); //This works well
return results;
});
} catch (e) {
throw Error('Error Loading Data:- ' + e.message);
}
};
SyncController.js
const syncRepo = require('../../../Repositories/Sync/SyncRepository');
exports.getItem = async (req, res) => {
try {
await syncRepo.ItemRepo(7)
.then(element => {
console.log(element);
return res.json(element); //This return null
});
// return await res.json(await syncRepo.ItemRepo(7));
} catch (e) {
return res.status(400).json({ status: 400, message: e.message });
}
};
You are mixing async/await and traditional Promise syntax. Try this :
SyncRepository.js
const mongoose = require('mongoose');
exports.ItemRepo = limit => {
return mongoose.connection.db.collection('items_1087342')
.find({}, {timeout: false})
.limit(limit)
.exec() // see #Enslev's explanation in the comments
};
SyncController.js
const syncRepo = require('../../../Repositories/Sync/SyncRepository');
exports.getItem = async (req, res) => {
try {
let element = await syncRepo.ItemRepo(7)
return res.json(element);
} catch (e) {
return res.status(400).json({ status: 400, message: e.message });
}
};

promise returns undefined in node module.exports

The Promise returns undefined when trying to log it in routes.js, however works fine when logging in queries.js. How should i change the promise to correctly return a response to routes.js?
in queries.js:
const rsClient = require('./client.js');
const query = {
one: 'SELECT * FROM my.db'
}
module.exports = {
rsProdRecs: (req, res) => {
rsClient.query(query.one)
.then(res => {
return res;
})
.catch(err => console.log(err));
}
};
in routes.js
var express = require('express');
var router = express.Router();
var queries = require('../queries');
router.get('/', function(req, res, next) {
const data = queries.rsProdRecs();
console.log(data)
res.send(data);
});
module.exports = router;
There's a few issues with your code. The first issue has already been pointed out by other users, you need to return the promise from rsProdRecs. The then and catch blocks are also problematic as well as how you are consuming the method in your route, as described in the code below:
module.exports = {
rsProdRecs: (req, res) => {
return rsClient.query(query.one);
// This is redundant, you're not transforming res in any way so this can be omitted.
// .then(res => {
// return res;
// })
// This will cause the promise to return 'undefined' if rsClient.query(...) rejects,
// instead error handling should be done in the calling function.
// .catch(err => console.log(err));
}
};
And you can refactor your route to properly consume your Promise returning method:
router.get('/', function (req, res, next) {
// We cannot consume the "data" directly, we must wait for the promise to resolve.
queries.rsProdRecs()
.then((data) => {
console.log(data);
res.send(data);
})
.catch((err) => {
console.log(err);
res.status(500); // insert correct error response here
});
});
Or use async/await since you are already using ES6 funcionality:
router.get('/', async function (req, res, next) {
try {
const data = await queries.rsProdRecs();
console.log(data);
res.send(data);
} catch (e) {
console.log(err);
res.status(500);
}
});
Did you try add return statement?
rsProdRecs: (req, res) => {
return rsClient.query(query.one)
.then(res => {
return res;
})
.catch(err => console.log(err));
}

Render results of two different queries at the same time in Node.js res.render

I am trying to show results of two SQL queries in one page. My code is in module.exports block and the whole application in written in Node.js Express. This returns an error "Cannot read property 'length' of undefined".
var message = "some random text";
var res_points, res_types;
db.query(query, (err, result) => {
if (err) {
res.redirect('/');
}
res_points= result;
});
db.query(query2, (err, result) => {
if(err) {
res.redirect('/');
}
res_types = result;
});
res.render('index.ejs', {
title: message,
,points: res_points
,types: res_types
});
When I do it like this, it works:
db.query(query, (err, result) => {
if (err) {
res.redirect('/');
}
res.render('index.ejs', {
title: message,
points: result
});
});
What am I doing wrong? Or better said, how can I pass results of those two queries into the render function?
The cleanest approach here is to use Promises & Promise.all. For that you will need to wrap db.query in a Promise.
// You can use Util.promisify too
const queryWrapper = (statement) => {
return new Promise((resolve, reject) => {
db.query(statement, (err, result) => {
if(err)
return reject(err);
resolve(result);
});
});
};
app.get('/some-route', (req, res, next) => {
const message = "some random text";
Promise.all([
queryWrapper(query),
queryWrapper(query2)
])
.then(([points, types]) => {
res.render('index.ejs', {
title: message,
points,
types
});
})
.catch(err => {
console.error(err);
res.redirect('/');
})
});
Note: If you're using MySQL, the mysql2 package offers promise support, so you can avoid the Promise wrapper.
I found a workaround like this, but I really don't think this is the only, corrent and elegant way how to do it:
let res_points, res_types;
db.query(query, (err, result) => {
if (err) {
res.redirect('/');
}
db.query(query2, (err2, result2) => {
if(err2) {
res.redirect('/');
}
res.render('index.ejs', {
title: "Welcome to Hamburg Map | View Points"
,points: result
,types:result2
});
});
});

Categories

Resources