JS mysql query result - javascript

I'm quite new in Node JS and I'm trying use a mysql DB.
I have try different thing like using promise to get the result of my query but the await is skip and the promise is pending.
I'm kinda lost if someone can explain me how it works.
import * as CMD from "../command/importCommand.js";
export class Message {
constructor(bot, database) {
this.bot = bot;
this.db = database;
}
eventHandler(msg) {
const guild = msg.guild;
const prefix = this.db.getPrefixFromGuild(guild);
console.log(prefix);
//
//
}
}
import * as mysql from "mysql";
export class Database {
constructor() {
this.db = new mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
this.db.connect(err => {
if (err) throw err;
console.log('DB connected');
});
}
async getPrefixFromGuild(guild) {
let prefix = await this.getPrefixFromGuildId(guild.id);
return prefix;
}
async getPrefixFromGuildId(guildId) {
let prefix = await this.query("select prefix from serveur where id_serveur=" + guildId + ";");
return prefix;
}
query(sql) {
return this.db.query(sql, (err, rows) => {
if (err)
throw err;
console.log(rows);
return rows;
});
}
}

Your eventHandler is not an async function and does not await the promise returned from getPrefixFromGuild(). The console.log() statement just logs the promise, not its result. Try this:
async eventHandler(msg) {
const guild = msg.guild;
const prefix = await this.db.getPrefixFromGuild(guild);
console.log(prefix);
}
Please also note that if you access an instance of your Database class right after creation, it might not be initialized since the constructor ist not waiting for the conntect() to complet (it shouldn't but you should find another way to prevent access to an uninitialized Database object).

Related

Async await problem in nodejs sequelize connection string

function credential(secretFromVault) {
const creddetails = new ClientSecretCredential(clientId, tenantId, cleintSecret);
// Build the URL to reach your key vault
const url = `https://<vaultName>.vault.azure.net/`;
// Lastly, create our secrets client and connect to the service
const client = new SecretClient(url, creddetails);
const secretName = secretFromVault;
return new Promise(resolve => {
client.getSecret(secretName).then(latestSecret => {
console.log(`value from secret is`, latestSecret.value);
resolve(latestSecret.value)
})
})
}
const dbUserName = credential(constants.pgDbUserName)
const dbPassword = credential(constants.pgDbPassword)
const hostname = constants.pgHostname;
const port = constants.pgPort;
const dbName = constants.pgDbName;
const sequelize = new Sequelize(dbName, dbUserName, dbPassword, {
host: hostname,
port: port,
dialect: constants.dialectName,
logging: false,
pool: {
max: constants.pgMaxPoolConnections,
min: constants.pgMinPoolConnections,
acquire: constants.pgMakeConnectionTimeOut,
idle: constants.pgIdleTimeout
}
});
sequelize.authenticate()
.then(() => {
console.log('Successfully connected.');
User.sync();
Credentials.sync();
App.sync();
Entity.sync();
EntityField.sync();
Relationship.sync();
})
.catch(err => console.log('Error: ' + err))
I am using the above code to make connection to postgres database. But I am receiving below error on execution of node index command, index.js is not attached here.
I want dbUSerName and dbUserpassword values to be passed in the sequelize connection string after fetched from the vault. but the values are promise which I am not able to resolve.
error: uncaughtException: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Promise
credential function returns Promise, you need to call it as a promise function.
You can read about promises here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
I think it will be better to wrap your code in a async function and use await before calling credential
async function main() {
const dbUserName = await credential(constants.pgDbUserName);
const dbPassword = await credential(constants.pgDbPassword);
// Your code
}
main();

js doesnt execute extern function to recieve data from db

I'm trying to receive same version data from my MySQL (MariaDB) Server.
For better maintenance i created one connection Object to handle all database queries.
However when I query some data, it seems like it isn't executed in time, but later when the first await command appears.
dbControl.js :
var mysql = require('mysql');
function getConnection(){
let dbConnection = mysql.createConnection({
host: "localhost",
user: "root",
password: ""
});
dbConnection.connect(function (err) {
if (err) throw err;
});
this.get_version = function() {
let sql = 'SELECT * FROM versionControl ORDER BY id DESC LIMIT 1;'
dbConnection.query(sql, function (err, result) {
if (err) throw err;
console.log("vData:", result);
return result;
});
}
}
module.exports.getConnection = getConnection;
dataHandler.js:
const browserControl = require('./browserControl');
const dbControl = require('../db/dbControl');
const dbConnection = new dbControl.getConnection();
let versionData;
// Here it should be executed -->
versionData = dbConnection.get_version();
console.log(versionData);
async function get_something(){
// Here it is executed -->
const browser = await browserControl.startBrowser();
//......
}
There is a 3th file which simply controls the program. At the moment it just executes the function get_something() like:
const originData = require('./dataHandler.js');
let data = originData.get_something();
console.log(data);
P.s.: its all running with node, thanks in advance ;_)
Your get_something() is marked as async.
Call it with await get_something() or get_something().then(console.log).
Ok, I got a solution. The SQL query function returns a promise now and I created an extra "getVersion"-async-function which is waiting for the resolve of the promise. Thus the promise waits for the db answer and the rest waits until the promise is resolved.
the dataHandler.js now looks like this:
const browserControl = require('./browserControl');
const dbControl = require('../db/dbControl');
const dbConnection = new dbControl.getConnection();
async function getVersion() {
let versionData;
versionData = await dbConnection.get_version();
console.log(versionData);
}
getVersion();
async function get_something(){
const browser = await browserControl.startBrowser();
}
and the query-function now looks like this:
this.get_version = function() {
let sql = 'SELECT * FROM versionControl.lol_scraper ORDER BY id DESC LIMIT 1;'
return new Promise(resolve => {
dbConnection.query(sql, function (err, result) {
if (err) throw err;
console.log("vData:", result);
resolve(result);
})
});
P.s.: still open for smarter or more modern solutions ;_)

Async Mongo DB Query

In my code, I am sending a query to my Mongo database. The method findUser() shall return the response of this query. The query works fine, tested with console.log(users).
The problem is the function returns null, it doesn't wait till the query got a response to return the var foundUser.
How could I use await/async in this case in order to wait for the query response before returning anything ?
function findUser(username) {
foundUser = null
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology : true});
client.connect(err => {
const collection = client.db("YourCV").collection("Accounts");
result = collection.findOne({username : username }, function(err, user) {
console.log(user)
if(user){
foundUser = user
}
});
});
return foundUser
};
console.log(user) outputs :
{
_id: 601695084b28102500ae0015,
username: 'jetlime',
password: '$2b$10$EN5k/YKOMBgibqy62s0hGOX9MffHZtXkfsw0Du0j8QVS7mGab5FLi'
}
Many thanks
Update the code to the following:
async function findUser(username) {
const client = await MongoClient.connect(url, { useNewUrlParser: true })
.catch(err => { console.log(err); });
if (!client) {
return;
}
const collection = client.db("YourCV").collection("Accounts");
const user = await collection.findOne({username : username });
client.close(); // -> To be under finally clause.
return user;
};
And call the function with await findUser(username);
Caution: The above of connecting to DB is not recommended. You are establishing a DB connection for every function call. This quickly leads to running out of connections on the DB side when you have a large number of requests.
Move the DB connection establishing part to a commonplace and re-use the connection.
See whatever you do, any operation you perform with your database, it returns promise, so write async keyword before the name of your function in line 1 and then await keyword before your query in line 6, it will then behave like synchronous call and every line will execute accordingly
As you said, you need to use async/await operators for asynchron methods.
You have two choices:
1)Implement callback method on findUser
async function findUser(username, onUsersReady) {
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).connect();
const collection = await client.db("YourCV").collection("Accounts");
await collection.findOne({
username: username
}, function(err, user) {
console.log(user)
if (user) {
foundUser = user
onUsersReady(user);
}
});
};
2)Use function to return results directly
async function findUser(username) {
const client = await new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).connect();
const collection = await client.db("YourCV").collection("Accounts");
const foundUser = await collection.findOne({
username
});
return foundUser;
}

MongoDB reusable custom javascript module

I would like to create a local Javascript module I can "require" in other files to handle all MongoDB CRUD operations.
I wrote something as:
-- dbConn.js file --
require('dotenv').config()
const MongoClient = require('mongodb').MongoClient
const ObjectID = require('mongodb').ObjectID
let _connection
const connectDB = async () => {
try {
const client = await MongoClient.connect(process.env.MONGO_DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
})
console.log('Connected to MongoDB')
return client
} catch (err) {
console.log(error)
}
}
exports.findOne = async () => {
let client = await connectDB()
if (!client) {
return;
}
try {
const db = client.db("Test_DB");
const collection = db.collection('IoT_data_Coll');
const query = {}
let res = await collection.findOne(query);
return res;
} catch (err) {
console.log(err);
} finally {
client.close();
}
}
exports.findAll = async () => {
let client = await connectDB()
if (!client) {
return;
}
try {
const db = client.db("Test_DB");
const collection = db.collection('IoT_data_Coll');
const query = {}
let res = await collection.find(query).toArray();
return res;
} catch (err) {
console.log(err);
} finally {
client.close();
}
}
Then in another file (not necessary inside Express app), say
-- app.js ---
const findAll = require('./dbConn').findAll
const findOne = require('./dbConn').findOne
findAll().then(res => JSON.stringify(console.log(res)))
findOne().then(res => JSON.stringify(console.log(res)))
I wonder if it is correct?
I have to close the connection after each method/CRUD operation?
I was trying to use IIF instead of ".then", as:
(async () => {
console.log(await findOne())
})()
But I receive a weird error saying that findAll is not a function.
What's wrong with it?
Thanks.
It really depends on your use case which isn’t clear If you are using Express or just stand alone and how frequent are you planning to run app.js
Either way your code is expensive, each time you reference dbCon.js you are opening a new connection to the database.
So you can fix app.js by only requiring dbCon.js once and use it..
The best practice is to ofcourse use connection pooling https://www.compose.com/articles/connection-pooling-with-mongodb/

Node express app calling mssql is saying that Connection is closed

I have another app which uses express and routes but this new app i was slimming it down. I know the connection string stuff is correct
script.getQuestions(connection);
script.getQuestions = function(connection,req, res){
console.log(connection);
}
I have read that some people said online to change to use a promise for async fixes this... problem is that with my function having req and res i don't know how to pass those in when i even try to refactor with a promise
"ConnectionError: Connection is closed"
"(module.js:487:32) code: 'ECONNCLOSED', name: 'ConnectionError' }"
What I call up (script) is
var sql = require('mssql');
exports.getQuestions = function(connection, req,res){
console.log(connection);
var request = new sql.Request(connection);
var query = 'select * from Question'
request.query(query).then(function(resultset){
res.json(resultset.recordset);
}).catch(function(err){
console.log(err);
//res.json(err)
})
}
it's a bit hard to understand what you're doing there. But here is an promise example to use mssql
const sql = require('mssql')
sql.connect(config).then(pool => {
// Query
return pool.request()
.input('input_parameter', sql.Int, value)
.query('select * from mytable where id = #input_parameter')
}).then(result => {
console.dir(result)
// Stored procedure
return pool.request()
.input('input_parameter', sql.Int, value)
.output('output_parameter', sql.VarChar(50))
.execute('procedure_name')
}).then(result => {
console.dir(result)
}).catch(err => {
// ... error checks
})
sql.on('error', err => {
// ... error handler
})
source: https://www.npmjs.com/package/mssql#promises

Categories

Resources