Variable cannot be change inside findOne - node.js

I want to make a quick Util file which would contain multiple functions such as an user_id to his name. As the image under shows, I tried to save the value throughout the code but the variable "name" doesn't get affected inside the .then(user => {}) for some reasons
I tried returning directly the value without using variable to save it.
I debugged and code runs fine and it gets into the if(!user){}else{}perfectly.
The user returned by Mongoose works and I can console log the user.username (Cannot return it, either can I save it to a variable, which is what i'm doing on the code under)
const User = require('../models/users')
exports.id2name = (id) => {
let name = 'none'
User.findOne({_id: id}).then(user => {
if (!user) {
name = 'Unknown'
} else {
name = user.username
}
}).catch(err => console.log(err))
return name
}
I don't get any errors on my console. It is returning 'none' as a result even if it gets into the else statement inside the mongoose request.

You are getting this result for asynchronous behaviours of JavaScript.
You can try this code for getting the desired result.
exports.id2name = async (id) => {
try{
let name = 'none'
const user = await User.findOne({_id: id});
if(user) {
name = user.username;
} else {
name = 'Unknown';
}
return name;
} catch(e) {
console.log(e);
}
}

It's asynchronous return. I mean you may need to use callback, Promise or other asynchronous way to deal with it, for example:
const User = require('../models/users')
exports.id2name = (id, callback) => {
User.findOne({_id: id}).then(user => {
if (!user) {
callback(null, 'Unknown')
} else {
callback(null, user.username)
}
}).catch(callback)
}
or promise:
const User = require('../models/users')
exports.id2name = (id) => {
return new Promise((resolve, reject) => {
User.findOne({_id: id}).then(user => {
if (!user) {
resolve('Unknown')
} else {
resolve(user.username)
}
}).catch(reject);
});
}

Related

Return items from text file as list in nodeJS

Can someone tell me how to return items in a text file as a list. I'm writing code for basic authentication. It registers users then stores their information(first name, last name, gender, password) in a .txt file. I want to be able to confirm a user's password from their file in order to log them in. I'm using the str.split method but it just returns 'undefined'. The 'username' argument in the code below indicates the file name without .txt added to it
const read = (username) => {
fs.readFile(`${dirPath}/${username}.txt`, 'utf8', (err, item) => {
console.log(item);
})
};
const authenticatedUser = (username) => {
var validUser = doesUserExist("./Database", username);
if (validUser = true) {
var user = read(username);
var userArray = String(user).split(",");
console.log(userArray);
}
};
function doesUserExist (userPath, username) {
fs.readdir(userPath, (err, files) => {
if (err) {
console.log("error");
} else {
files.forEach(file => {
if (file == `${username}.txt`) {
return true;
} else if (file !== `${username}.txt`) {
return false;
}
});
}
});
};
You are calling read() as a function that returns a string when it in fact just executes a fs.readFile() and then returns nothing.
The quickest way to fix this would be to use fs.readFileSync() and make sure to return that value from read().
const read = (username) => {
return fs.readFileSync(`${dirPath}/${username}.txt`, {encoding:'utf8'});
};
A function that does not return a value intrinsically returns undefined.
A more idiomatically correct solution might involve switching to async code:
const read = async (username) => {
return await fs.promises.readFile(`${dirPath}/${username}.txt`, {encoding:'utf8'});
};
const authenticatedUser = async (username) => {
var validUser = await doesUserExist("./Database", username);
if (validUser = true) {
var user = await read(username);
var userArray = String(user).split(",");
console.log(userArray);
}
};
const doesUserExist = async (userPath, username) {
let returnVal = false;
const files = await fs.promises.readdir(userPath);
files.forEach(file => {
if (file == `${username}.txt`) {
returnVal = true;
});
return returnVal;
};
Using async and await, you can read your code as if it was synchronous.

Express router not awaiting the forEach loop

Express router is not awaiting my forEach loop and sends the old unmanipulated object as a response instead of the new manipulated data.
Here I am using Sequalize as my ORM.
router.get('/', async (req,res) => {
try {
let trainings = await db.Training.findAll();
let locations = await db.Location.findAll();
await locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
res.status(200).json({
training:trainings
})
} catch(err) {
console.log(err);
res.status(404).json({
message : err
})
}
})
Basically you are using the await keyword against a synchronous process which is
locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
These lines of code doesn't return any promise or behave like a promise. So one solution can be having a function
function modify(trainings,locations){
return new Promise((resolve,reject)=>{
locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
resolve('done')
})
}
then have it like this
let trainings = await db.Training.findAll();
let locations = await db.Location.findAll();
await modify(trainings,locations)
or you can simply remove the await keyword from your current state of code.

Why is my return variable value not being recognised in node module

I have got a node file requesting a return variable from another module page. All the data functions "work" but the "return query" is not sending the query value back to my initial request and my existingUser variable is undefined. In the console logs checks I put in the existingUser ones displays before the query one. It is like the await request is being ignored.
Any help appreciated...and I'm a newbie to all this!
Request page -
const sqlRequests1 = require('./sqlAdmin/sqlRequests1');
.
.
.
app.post('/', async (req, res) => {
const { club, first_name, last_name, email, tel, address, post_code, password, passwordConfirmation} = req.body;
let existingUser = await new sqlRequests1.Queries('contact',email).getAll();
console.log(`existingUser is ${existingUser}`); //THIS CONSOLE LOG RETURNS "undefined"
if (existingUser) {
return res.send('Email in use');
}
if (password !== passwordConfirmation) {
return res.send('Passwords must match');
}
res.send('Account created!!!');
});
Module page - sqlRequests1
class Queries {
constructor(table, selection) {
this.table = table;
this.selection = selection;
console.log(selection); //THIS DATA CHECK WORKS
if(!table) {
throw new Error('Need a table to connect to');
};
};
getAll() {
//Confirm if the emasil exists - if it does then give error message
let q = 'SELECT * FROM ?? ';
connection.query(q, this.table, function (error, results,fields) {
if (error) throw error;
const query = (results[0].email);
console.log(`query is ${query}`); //THIS PROVIDES THE CORRECT DATA
return query; //THIS RETURN IS NOT GETTING BACK TO existingUser variable?
});
};
};
module.exports.Queries = Queries;
If you want to use await and block the code from moving further, you have to convert your get all function to return a promise....
getAll() {
new Promise((resolve,reject) => {
//Confirm if the emasil exists - if it does then give error message
let q = 'SELECT * FROM ?? ';
connection.query(q, this.table, function (error, results,fields) {
if (error) reject(error);
const query = (results[0].email);
console.log(`query is ${query}`); //THIS PROVIDES THE CORRECT DATA
resolve(query) //THIS RETURN IS NOT GETTING BACK TO existingUser variable?
});
})
}
Promise was the way to go but it just missed the return
getAll() {
return new Promise((resolve,reject) => { //ADDING return here fixed it
//Confirm if the emasil exists - if it does then give error message
let q = 'SELECT * FROM ?? ';
connection.query(q, this.table, function (error, results,fields) {
if (error) reject(error);
const query = (results[0].email);
console.log(`query is ${query}`); //THIS PROVIDES THE CORRECT DATA
resolve(query) //THIS RETURN IS NOT GETTING BACK TO existingUser variable?
});
})
}

require function doesn't work inside a function within a method

I'm using Node.js to build the back-end of an application and I'm using postgresql as database. I'm having problem with the implementation of the login. More precisely I am using the bcrypt module and it doesn't work in the function called by the execution of the query. Here is the code:
const login = async (request, response) => {
const username = request.body.username
console.log(request.body)
pool.query('SELECT * FROM public."User" WHERE username = \'{' + username + '}\'', (error, results) => {
if (error) {
return response.status(400).send("Cannot find user: "+username)
}
try {
if(await bcrypt.compare(request.body.password, results.rows[0].password.toString())) {
response.send('Success')
} else {
response.send('Not allowed')
}
} catch {
response.status(500).send("Server error")
}
})
}
The problem is that I execute my query and it works, but when it arrives in the second if statement the problem is this:
if(await bcrypt.compare(request.body.password, results.rows[0].password.toString())) {
^^^^^^
SyntaxError: Unexpected identifier
I cannot figure out how to solve it.
I've also tried to take the try/catch statement outside the pool.query function, by saving the retrieved password in a variable, as follows:
const login = async (request, response) => {
const username = request.body.username
var hashedPassword
console.log(request.body)
pool.query('SELECT * FROM public."User" WHERE username = \'{' + username + '}\'', (error, results) => {
if (error) {
return response.status(400).send("Cannot find user: "+username)
}
hashedPassword = results.rows[0].password.toString()
})
try {
if(await bcrypt.compare(request.body.password, hashedPassword)) {
response.send('Success')
} else {
response.send('Not allowed')
}
} catch {
response.status(500).send("Server error")
}
}
But in this way the try/catch statement is executed before the query and actually I don't even know if variable "hashedPassword" can be set in such a way, because I always find it as "undefined"

How can I get a value returned from a then clause when select data using mysql

I am trying to finish a login functionality with mysql and express. I got a work_id and a user_password, and I want to use the work_id to find whether the user exists in my database. I use promise to do this, I can log the selected user information in the console, but the promise is always pending, and the web storm console didn't terminate.
What I want is a boolean value from the promise, whether the user exists or not.
Here is my code:
query.js.
const pool = require('./connect');
module.exports = {
query: function (sqlString, params) {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sqlString, params, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release()
})
}
})
})
}
}
sqlCRUD.js, about the sql statement
const user = {
queryByWorkId: 'select * from user_info where work_id=?',
queryAll: 'select * from user_info',
resetPassword: 'update user_info set user_password = ? where work_id = ?',
};
user.js, I execute the test here.
const Model = require('./main')
const crypto = require('crypto')
const _ = require('./query')
const $sqlQuery = require('./sqlCRUD').user
class User{
// others
static findOne(form={}) {
const { work_id, user_password } = form
return _.query($sqlQuery.queryByWorkId, work_id)
.then(res => {
console.log(res)
if (res.length > 0) {
const u = res[0]
return u
}
return false
})
.catch(err => {
console.log('User.findOne error', err)
return {
errmsg: JSON.stringify(err)
}
})
}
Here is my test, in user.js
const test = () => {
const form = {
work_id: '007',
user_password: 'root',
}
const r = User.findOne(form)
console.log('r', r)
}
And this is the output:
I am not allowed to embed a picture here, so SO generates a link
I got confused about this: in my query.js file, I return a promise, in my User.findOne(form={}) method, I call it with a then and catch,
return _.query($sqlQuery.queryByWorkId, work_id).then(res => console.log(res)).catch(err => console.log(err)), but the console did't terminate, and I just got a Promise { }.
What's wrong with my code? How can I get a value returned from a then clause in promise when select data using mysql? Thanks in advance.

Resources