This is the very basic route I am using:
router.get('/:date', async (req, res) => {
let tracks = []
let query = 'SELECT * from `tracks` where `playlistDate` = \''+req.params.date+'\''
let result = await pool.query(query)
console.log(result)
})
I know this by itself won't work, but what do I need to do to be able to use await on the query function like this?
This is the pool, with the credentials and addr changed.
var pool = mysql.createPool({
poolLimit : 10,
host : 'HOST',
user : 'USER',
password : 'PASS',
database : 'DB'
});
Maybe this logic would help. It depends on how you structured it.
var pool = mysql.createPool({
poolLimit : 10,
host : 'HOST',
user : 'USER',
password : 'PASS',
database : 'DB'
});
const getTracks = (date) => {
return new Promise((resolve, reject) => {
let query = 'SELECT * FROM tracks WHERE playlistDate = ?'
pool.query(query, [date], (err, res) => {
if (err) {
reject(err);
return;
}
resolve(res);
})
})
};
router.get('/:date', async (req, res) => {
try {
let tracks = await getTracks(req.params.date);
return res.status(200).json(tracks);
} catch (err) {
return res.status(400).json(err);
}
})
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;
The client.mysqllocal function is supposed to return rows.
My current code: https://pastebin.com/hgt2DwSY
const mysql = require('mysql2');
let pool = mysql.createPool({
connectionLimit : 10,
host : 'localhost',
user : 'user',
password : 'passwd',
database : 'database',
waitForConnections: true,
queueLimit: 0
});
client.mysqllocal = async function localmysql(mySQL_db, mySQL_query){
let rows;
pool.getConnection(async function(err, conn) {
if (err){
console.log(err);
}
conn.changeUser({database : mySQL_db}, function(err) {
if (err){
console.log(err);
}
});
conn.query(mySQL_query), function (error, results, fields) {
rows = results
}
conn.release()
})
return rows;
}
let func = client.mysqllocal('database','SELECT * FROM `guild_config` WHERE `guild_id` = "guildid"');
console.log(func);
P.S. this is a code snippet, I have a client defined above :) .
In this instance I would probably promisify your querying function
const mysql = require('mysql2');
let pool = mysql.createPool({
connectionLimit : 10,
host : 'localhost',
user : 'user',
password : 'passwd',
database : 'database',
waitForConnections: true,
queueLimit: 0
});
client.mysqllocal = function localmysql(mySQL_db, mySQL_query) {
return new Promise((resolve, reject) => {
let rows;
pool.getConnection(async function(err, conn) {
if (err){
reject(err);
}
conn.changeUser({database : mySQL_db}, function(err) {
if (err){
reject(err);
}
});
conn.query(mySQL_query), function (error, results, fields) {
rows = results
}
conn.release()
})
resolve(rows);
});
}
client.mysqllocal('database','SELECT * FROM `guild_config` WHERE `guild_id` = "guildid"').then(func => console.log(func));
const mysql = require('mysql2');
let pool = mysql.createPool({
connectionLimit : 10,
host : 'localhost',
user : 'user',
password : 'passwd',
database : 'database'
});
client.getLocal = (db, query, callback) => {
pool.getConnection((err, con) => {
if(err) reject(err);
con.changeUser({
database: db
}, (err) => { if(err) reject(err) });
con.query(query, (error, result, fields) => {
return callback(result);
})
})
}
client.getLocal('dbname', 'query', (result) => {
console.log(result)
})
What I did here was specify a function inside a function so that I can play with the data that the query gives me, and doesn't require async either! Promises are much more preferred but I consider my callbacks to be a bit more flexible, and beginners are prone to confusion when using promises, just like I was! I'd say use a promise as the question above me does.
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've been reading about async and await in JS and tried to implement them in my code (which I totally messed up).
Here is my JS.
var express = require('express');
var router = express.Router();
var jsforce = require('jsforce');
const SEC_TOKEN = 'SEC_TOKEN';
const USER_ID = 'USER_ID';
const PASSWORD = 'PWD';
const { default: axios } = require('axios');
router.get("/", async (req, res, next) => {
await initConnect;
await soqlData;
await slackPostTest;
});
initConnect = async () => {
var conn = new jsforce.Connection({
loginUrl: 'https://login.salesforce.com'
});
await conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err)
console.log(err);
else {
console.log(userInfo.Id);
}
});
}
soqlData = async () => {
await conn.query('Select Id, Name from Account LIMIT 1', (err, data) => {
if (err)
console.log(err);
else
return data.records[0];
})
}
slackPostTest = async () => {
await axios.post('SLACK_WEBHOOK', {
"text": "soqlRes"
})
}
module.exports = router;
What I am trying to achieve?
Initialize my connection by passing in SEC_TOKEN, USER_ID, PASSWORD to my initConnect function this will give me a connection (conn).
Use this conn and query my salesforce instance and get some other data.
post some message(currently irrelevant, but will hook up with the above response later) to my slack endpoint.
Also can someone please give me a little detailed explanation of the solution (in terms of async/await)?
Thanks
Assuming everything else about your JsForce API usage was correct (I have no experience with it, so I can't say), here's how to promisify those callback-based APIs and call them.
var express = require("express");
var router = express.Router();
var jsforce = require("jsforce");
const SEC_TOKEN = "SEC_TOKEN";
const USER_ID = "USER_ID";
const PASSWORD = "PWD";
const { default: axios } = require("axios");
router.get("/", async (req, res, next) => {
const { conn, userInfo } = await initConnect();
const data = await soqlData(
conn,
"Select Id, Name from Account LIMIT 1",
);
await slackPostTest(data.records[0]);
});
function initConnect() {
const conn = new jsforce.Connection({
loginUrl: "https://login.salesforce.com",
});
return new Promise((resolve, reject) => {
conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err) return reject(err);
resolve({ conn, userInfo });
});
});
}
function soqlData(conn, query) {
return new Promise((resolve, reject) => {
conn.query(query, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
}
function slackPostTest(soqlRes) {
return axios.post("SLACK_WEBHOOK", {
text: soqlRes,
});
}
module.exports = router;
I'm trying to create an api route using Node and Express and I must say I don't have much experience with it. Right know I have the following code:
app.get('/api/place/:id', (req, res) => {
var id = req.params.id;
var message_error = '{"status": "failed", "message": "Unable to fetch data"}';
db.query("SELECT `id`, `user`, `lat`, `lon`, `elevation`, `rating`, `rating_count`, `country`, `continent`, `locality` FROM `t_points` WHERE id = ?", [id], (err, res1) => {
if(err) {
res.json(message_error);
} else {
//Store the user id from the points table and use it to fetch user datas
var userId = res1[0].user;
if(userId != null) {
db.query("SELECT `id`, `name` FROM `t_users` WHERE `id` = ?", [userId], (err, res2) => {
if(err) {
res.json(message_error);
} else {
//Final json structure
res.json({
id: res1[0].id,
lat: res1[0].lat,
lon: res1[0].lon,
elevation: res1[0].elevation,
rating: res1[0].rating,
rating_count: res1[0].rating_count,
user: {
id: res2[0].id,
name: res2[0].name
}
});
}
});
} else {
res.json({
id: res1[0].id,
lat: res1[0].lat,
lon: res1[0].lon,
elevation: res1[0].elevation,
rating: res1[0].rating,
rating_count: res1[0].rating_count
});
}
}
});
});
I'm hard-coding the json structure so if the userId in my table is null I don't print the user object in the json, otherwise I print it. But that's not a good idea, as I will also add more queries in the same route. Is there a simple way to create just one json at the end of all the queries and if some values are null not showing it?
Also, would it be better to use async and await functions to do it, instead of this way?
Thanks!
use util maybe better way to get result when querying data.
const mysql = require('mysql');
const util = require('util');
// ? connection pool
let db = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
port: 3306,
user: 'root',
password: 'secretpass',
database: 'yourdatabasename'
});
// ? check connection
db.getConnection((err, connection) => {
if (err) {
console.log('database connection failed');
} else {
console.log('database connection resolved');
connection.release();
}
});
// ? formatter query
function queryString(spName, ...queryParam) {
return mysql.format(spName, queryParam);
}
// ? do query
let performQuery = util.promisify(db.query).bind(db)
module.exports = {
performQuery,
queryString
}
then use the function above like this :
app.get('/api/place/:id', async (req, res) => {
const id = req.params.id;
const message_error = '{"status": "failed", "message": "Unable to fetch data"}';
try {
let prepareOne = queryString(SELECT `id`, `user`, `lat`, `lon`, `elevation`, `rating`, `rating_count`, `country`, `continent`, `locality` FROM `t_points` WHERE id = ?", id);
let resultOne = await performQuery(prepareOne);
let userId = resultOne[0].user;
if (userId != null) {
let prepareTwo = queryString("SELECT `id`, `name` FROM `t_users` WHERE `id` = ?", userId);
let resultTwo = await performQuery(prepareTwo);
res.json({
...resultOne,
user: {
...resultTwo
}
});
}
} catch (err) {
res.send(message_error);
}