During the launch my website i can't connection to my database. It doesn't get errors and the page is loading infinitely. Who know answer on this question give me some advise.
I work in (Node.js,PostgreSQL,Express)
from file config_db
const client_admin1 = {
user:'a_role',
database:'road_db',
password: '12345',
host:'localhost',
port:5432,
max:10,
idleTimeoutMillis: 30000
}
const pg = require("pg")
const client_login = require("../config/config_db");
searchUser(req, res) {
const db = new pg.Pool(client_login.client_admin1)
db.connect(function(err, client, done){
if(err){
return console.error('connection problems')
}
client.query('SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2',[req.body.login, req.body.password], function(err, result){
done()
if (err || result.rowCount <= 0){
res.render('error_login_choice')
return console.error("")
}
if(result.rows[0].role_name === "client")
{
cln.getClients(req,res)
}
})
}
try this executeQuery method
const pg = require('pg');
const pgconfig = {
user: process.env.DATA_BASE_USER,
database: process.env.DATA_BASE_NAME,
password: process.env.DATA_BASE_PASSWORD,
host: process.env.DATA_BASE_HOST,
port: process.env.DATA_BASE_PORT,
};
console.log(`DB | Settings: ${JSON.stringify(pgconfig)}`);
const pool = new pg.Pool(pgconfig);
pool.on('connect', () => {
console.log('DB | new client connection establish.');
});
pool.on('error', err => {
console.error(`idle client error, ${err.message} | ${err.stack}`);
});
pool.connect(err => {
if (err) {
console.error(`PostgreSQL input: ${err}`);
} else console.log('DB | connection establish.');
});
const executeQuery = async(sql, data) => {
logger.debug(`sqlToDB() sql: ${sql} | data: ${data}`);
try {
const result = await pool.query(sql, data);
return result;
} catch (error) {
console.error(error.message);
}
};
module.exports = {
executeQuery,
};
usage:
const dbHandler = require('./db');
const getLogedInUser = login,password => {
const selectFieldsQuery = `'SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2'`;
return dbHandler.executeQuery(selectFieldsQuery, [login,password]).then(e => e.rows);
};
Related
I am trying to convert mySQL connection from promise to asycn await so far I have the following setup:
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
let usersDB = {};
usersDB.all = () => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
});
};
usersDB.one = (id) => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users WHERE id = ?", [id], (err, results) => {
if (err) {
return reject(err);
}
return resolve(results[0]);
});
});
};
module.exports = usersDB;
Is there a way to convert this codes:
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
to async await and make the code more compress or succint?
UPDATE: on my router, I have these codes:
const router = express.Router();
router.get("/", async (req, res) => {
try {
let results = await db.all();
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
router.get("/:id", async (req, res) => {
try {
let results = await db.one(req.params.id);
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
So it just fine calling async await twice?
You can convert any callback function to promise by using util.promisify
const util = require('util')
// ....
const query = util.promisify(pool.query)
// ... inside some async function
const users = await query("SELECT * FROM users;")
// or promise style
query("SELECT * FROM users;")
.then((users) => {
console.log(users)
})
.catch(console.error)
usersDB.one = (id) => {
try {
const users = pool.query("SELECT * FROM users WHERE id = ?", [id]);
return users;
} catch (e) {
throw e;
}
};
Or more simply,
usersDB.one = (id) => pool.query("SELECT * FROM users WHERE id = ?", [id]);
What you want to do is to promisify the DB call. You can acheive this by factorisation :
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
function promisify(...args){
return new Promise((resolve, reject) => {
pool.query(...args, (err, result) => {
if(err) reject(err);
resolve(result);
});
});
}
let usersDB = {};
//Then you can call it this way :
usersDB.all = async () => {
return await promisify("SELECT * FROM users");
//Note that you can avoid to await there.
};
usersDB.one = async (id) => {
return await promisify("SELECT * FROM users WHERE id = ?", [id]);
};
module.exports = usersDB;
I'm very new to testing with Jest. I want to make a test to see if the following function returns user data from the database I have:
let dbConnect = require('../config/dbConnect');
let findUserByEmail = (email) => {
return new Promise(async (resolve, reject) => {
try {
dbConnect.query("SELECT * FROM user_login WHERE email = ?", email, function (error, results) {
if (error) reject(error);
let user = results[0];
if(user == undefined){
resolve()
}
resolve(user);
})
} catch (e) {
reject(e);
}
})
}
How would I go about making mock data to use in testing?
EDIT: Here is dbConnect:
let mysql = require('mysql');
let dotenv = require('dotenv');
dotenv.config({path: '../.env'});
let db = mysql.createConnection({
host: process.env.DATABASE_HOST,
database: process.env.DATABASE,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
});
db.connect(function (error) {
if (error) console.log(error);
else console.log("MYSQL Connected...");
});
module.exports = db;
Edit: fixed mistake
const mysql = require('mysql')
const mockQuery = jest.fn()
jest.mock('mysql', () => ({
createConnection: () => ({
connect: () => undefined,
query: mockQuery
}),
}))
describe('findUserByEmail', () => {
it('should resolve with the user when query suceeds', async () => {
mockQuery.mockImplementationOnce((sql, email, callback) => callback(null, ['TEST USER']));
expect(await findUserByEmail()).toBe('TEST USER');
})
});
I have a PUT in a REST API that should display an error message that says "upvoted already" if the vote_score is 1 (that is, they voted already), but instead I get a generic "internal server error" message in alert which is not good UX. That's always what the error will say with what I have tried so far.
How can I get my error message to display as "upvoted already"? Or for that matter, how can I get any error message to show up with a message? I hope I have provided enough information with the API code followed with the front-end code.
What I have tried thus far is trying different things like res.status(200).json({ error: err.toString() }); and next(err).
Hopefully something simple, I am hoping for a ELI5 type answer because I am a beginner and my error-handling game is weak. Thanks.
const db = require('../db');
const express = require('express');
const debug = require('debug')('app:api:vote');
const Joi = require('joi');
const auth = require('../middleware/auth');
const admin = require('../middleware/admin');
const { required } = require('joi');
const router = express.Router();
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
// general error handler
const sendError = (err, res) => {
debug(err);
if (err.isJoi) {
res.json({ error: err.details.map((x) => x.message + '.').join('\n') });
} else {
res.json({ error: err.message });
}
};
router.put('/upvote/:emojiId/', auth, async (req, res, next) => {
try {
const schema = Joi.object({
emoji_id: Joi.number().required(),
user_id: Joi.number().required(),
vote_score: Joi.number(),
});
const vote = await schema.validateAsync({
emoji_id: req.params.emojiId,
user_id: req.user.user_id,
vote_score: 1,
});
if (!(await db.findVoteByUser(vote.emoji_id, vote.user_id))) {
const upvote = await db.upvote(vote);
} else if ((await db.findVoteByUser(vote.emoji_id, vote.user_id)) == 1) {
throw new Error('Upvoted already');
}
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
res.json(upvoteScore);
} catch (err) {
res.status(500).json({ error: err.toString() });
}
});
module.exports = router;
And the front-end...
$(document).on('click', '.upvote-emoji-button', (evt) => {
const button = $(evt.currentTarget);
const emoji_id = button.data('id');
$.ajax({
method: 'PUT',
url: `/api/vote/upvote/${emoji_id}`,
data: emoji_id,
dataType: 'json',
})
.done((res) => {
if (res.error) {
bootbox.alert(res.error);
} else {
// $('#search-emoji-form').trigger('submit');
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
}
})
.fail((xhr, textStatus, err) => {
bootbox.alert(err);
});
});
try to replace
res.status(500).json({ error: err.toString() });
with
res.status(400).send(err.toString());
Documentation
Here is what I ended up doing. It took care of my error and a few other things too. :)
//setup
const db = require('../db');
const express = require('express');
const debug = require('debug')('app:api:vote');
const Joi = require('joi');
const auth = require('../middleware/auth');
const admin = require('../middleware/admin');
const { required } = require('joi');
const router = express.Router();
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
// general error handler
const sendError = (err, res) => {
debug(err);
if (err.isJoi) {
res.json({ error: err.details.map((x) => x.message + '.').join('\n') });
} else {
res.json({ error: err.message });
}
};
router.put('/upvote/:emojiId/', auth, async (req, res, next) => {
let vote = {};
try {
const schema = Joi.object({
emoji_id: Joi.number().required(),
user_id: Joi.number().required(),
vote_score: Joi.number(),
});
vote = await schema.validateAsync({
emoji_id: req.params.emojiId,
user_id: req.user.user_id,
vote_score: 1,
});
if (!(await db.findUserByID(req.user.user_id))) {
throw new Error('log in again.');
}
const tester = await db.findVoteByUser(vote.user_id, vote.emoji_id);
if (!(await db.findVoteByUser(vote.user_id, vote.emoji_id))) {
await db.upvotePost(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Upvote sent.';
const action = 'action';
upvoteScore[action] = 1;
res.json(upvoteScore);
} else if (tester.vote_score == -1) {
await db.upvotePut(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Downvote changed to upvote.';
const action = 'action';
upvoteScore[action] = 2;
res.json(upvoteScore);
} else {
await db.deleteVoteByUserIdAndEmojiId(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Upvote deleted.';
const action = 'action';
upvoteScore[action] = 3;
res.json(upvoteScore);
}
} catch (err) {
sendError(err, res);
}
});
module.exports = router;
and front end..
$(document).on('click', '.upvote-emoji-button', (evt) => {
const button = $(evt.currentTarget);
const emoji_id = button.data('id');
$.ajax({
method: 'PUT',
url: `/api/vote/upvote/${emoji_id}`,
data: emoji_id,
dataType: 'json',
})
.done((res) => {
if (res.error) {
bootbox.alert(res.error);
} else {
if (res.action == 1) {
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
} else if (res.action == 2) {
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().children().addClass('btn-primary').removeClass('btn-danger');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
} else if (res.action == 3) {
button.removeClass('btn-danger').addClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
}
}
})
.fail((xhr, textStatus, err) => {
bootbox.alert(err);
// alert(`${textStatus}\n${err}\n${xhr.status}`);
});
});
My question is similar to this.
However, mine runs in Node.js and it seems like a bit more complicated.
The server side wasn't built by me, but someone else that I can't contact. And he wrote code very differently.
And I have db.js and it looks like this:
And routes/email.js it uses db.js like this:
And when I click a button. I get this error:
db.emailRequest is not a function
in db.js, at the end of the file. It originally had this:
module.exports = new dbHelper;
And my style to use db.js in routers.
db.get().query(sql, input, function(err,res){
//TODO:
});
But it didn't work. So, I changed the end of db.js like this:
exports.get = function(){
console.log("exports.get");
return pool;
}
And also added some code in app.js like this:
db.connect(function(err){
if(err){
console.log('Unable to connect to MariaDB');
process.exit(1);
}
});
What should I do?
The full code of db.js is here:
const mariadb = require('mariadb');
var pool;
exports.connect = function(done){
console.log("Trying to connect DB...");
pool = mariadb.createPool({
host: 'localhost',
user: 'root',
password: 'xxxxxxx',
database:"XXXXX",
connectionLimit: 5 // Why 5 ???
});
pool.getConnection()
.then(conn => {
console.log("DB connected. id: " + conn.threadId);
conn.end(); //release to pool
}).catch(err => {
console.log("DB failed connection: " + err);
});
}
function makeToken(){
console.log("makeToken()");
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for(var i=0;i<32;i++){
text+=possible.charAt(Math.floor(Math.random()*possible.length));
}
return text;
}
function dbHelper() {
console.log("dbHelper()");
this.emailRequest = function(email,num){
console.log("emailRequest");
pool.getConnection().then(conn => {
conn.query("INSERT INTO email_verification(email, code) VALUES(?,?)",[email,num]);
conn.end(); //release to pool
})
.catch(err => {
console.log("not connected due to error: " + err);
});
}
// wait and process until getting return value because rv is needed.
this.verify = async function(email,num){
console.log("verify");
let conn;
var result = false;
try {
conn = await pool.getConnection();
// within 3minutes
const rows = await conn.query("SELECT count(*) FROM email_verificaiton WHERE email=? AND code=? AND req_time >= NOW() - INTERVAL 3 MINUTE",[email,num]);
if(rows[0]["count(*)"]>0){
result = true;
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
this.verifyUpdate = function(email,num){
console.log("verifyUpdate");
pool.getConnection()
.then(conn => {
conn.query("UPDATE email_verification SET status = 1 WHERE email=? AND code=?",[email,num]);
conn.end(); //release to pool
})
.catch(err => {
console.log("not connected due to error: " + err);
});
}
// wait and process until getting return value because rv is needed.
this.emailRegister = async function(email,pass,nick,devid){
console.log("emailRegister");
let conn;
var result;
try {
conn = await pool.getConnection();
var rows = await conn.query("SELECT count(*) FROM email_verification WHERE email=? AND status = 1",[email]);
if(rows[0]["count(*)"]>0){
rows = await conn.query("SELECT count(*) FROM member WHERE email=?",[email]);
if(rows[0]["count(*)"]==0){
var token = makeToken();
rows = await conn.query("INSERT INTO member (email,password,username,device_id,login_method,token) VALUES(?,?,?,?,0,?)",[email,pass,nick,devid,token]);
if(rows["affectedRows"]>0){
result = {result:true, code:200, message: "success",data:[{email:email,token:token}]};
} else{
result = {result:false,code:401, message:"db error"};
}
}else {
result = {result:false,code:402, message:"already registered id"};
}
} else {
result = {result:false,code:403, meesage:"email not verified"};
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
// wait and process until getting return value because rv is needed.
this.emailLogin = async function(email,pass,devid){
console.log("emailLogin");
let conn;
var result;
try {
conn = await pool.getConnection();
rows = await conn.query("SELECT * FROM member WHERE email=?",[email]);
if(rows.length==1){
if(rows[0]["password"]==pass){
var token = makeToken();
rows = await conn.query("UPDATE member SET device_id = ?, token = ? WHERE email=?",[devid,token,email]);
console.log(rows)
if(rows["affectedRows"]>0){
result = {result:true,message:"Sign up Success.", code:200, data:[{email:email,token:token}]};
} else{
result = {result:false,message:"db error",code:401};
}
} else {
result = {result:false,message:"wrong password",code:402};
}
}else {
result = {result:false,message:"not registered id",code:403};
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
}
//module.exports = new dbHelper;
exports.get = function(){
console.log("exports.get");
return pool;
}
I want to permanently store a result of a callback function, here is the code:
class constants {
constructor(){
this.acquire()
}
acquire() {
this.last_refresh = new Date().getDate();
require('./db_slave').then(conn => {
return conn.query("SELECT table_name FROM information_schema.tables where table_schema='gen'").then(result => {
this.tables = result
console.log(result)
});
}).catch(err => {
// handle error here
});
}
tables() {
this.refresh()
return this.tables
}
refresh() { if (new Date().getDate() != this.last_refresh) this.acquire() }
}
module.exports = constants
but this is obviously not working because this.tables = result doesnt do anything...
Here is the file that is being called by this promise:
var mysql = require('promise-mysql');
var db = require('./db')
module.exports = mysql.createConnection({
host: db.host,
user: db.user,
password: db.password
}).then(conn => {
console.log("connected to the DB");
return conn;
}).catch(err => {
console.log("error connecting to the DB", err);
throw err;
});
How do i permanently store the result in that callback?
here is how i used these:
var db_constants = require('./database_service/db_constants')
let cons = new db_constants()
console.log(cons.tables())