I know that mongodb has their own way of handling native promises with no rejection issues but I guess it doesnt work the same here with mysql. Is there anyway I can use .then in mysql? I was able to do it using more callbacks but I would like to use promises to make the solution cleaner or even use async/await if that makes it simpler too. I need to use a callback to jump to my server file, I have all my methods defined in my db file.
Server file:
app.get('/api/cows', (req, res) => {
db.reqMethods.getAll((err, data) => {
if (err) {
res.send('Error');
} else {
res.send(data);
}
});
});
db file:
const mysql = require('mysql');
const http = require('http');
const express = require('express');
const path = require('path');
const bodyParser = require("body-parser");
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'cowlist'
});
connection.connect((err) => {
if (err) {
console.log(err);
} else {
console.log('Connected to MySQL!')
}
});
// Your Database Queries Here!!
module.exports.reqMethods = {
// GET All Cow Info
getAll: function (callback) {
const query = connection.query('SELECT * FROM cows;');
query.then(data => callback(null, data));
});
};
// callback solution that I'd like to simplify:
// getAll: function (callback) {
// connection.query('SELECT * FROM cows;', (err, data) => {
// if (err) {
// callback(err, null);
// } else {
// console.log("DATA: \n", data);
// callback(null, data);
// }
// });
// }
Yes, this is possible by using mysql2 npm package.
So in your database.js file, use this method.
const mysql = require('mysql2');
var pool_connection = mysql.createPool({
host: '127.0.0.1',
port: 3306,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
connectionLimit: 10,
multipleStatements: true
});
pool_connection.getConnection((err) => {
if (err) console.log(JSON.stringify(err));
else {
console.log('Connected!')
}
});
module.exports = pool_connection.promise();
And in your models, you require the connection as follows and make use of async-await in a try-catch block.
const con = require('/path/to/your/database_file');
module.exports = class Messages {
constructor() { }
static async getMessage(arguments_here) {
const query = "some query here with params if required. Use ? for placing params and do not use string literal to embed params.";
try {
const [response] = await con.execute(query, [params]);
return response;
} catch (error) {
console.log(error);
return null;
}
}
}
And in your controller,
const Messages = require('../models/Messages');
const someFn = async (req, res) =>{
try {
const result = await Messages.getMessages('sample_arguments');
//do something with result
}
catch(err){
console.log(err);
}
}
Related
I'm having issues with SQL server. Every time I try to run this server and get the results from database, I got this error message:
ConnectionError: Connection is closed.
...
code: 'ECONNCLOSED'
I can't find any way to fix this, is there something missing I should have on my JS files?
connection.js
const sql = require('mssql/msnodesqlv8');
const dbSettings = {
user: '******',
password: '******',
server: "DESKTOP-*****\\SQLEXPRESS",
database: 'webstore',
driver: 'msnodesqlv8',
options: {
encrypt: true, // for azure
}
}
export async function getConnection() {
try {
const pool = await sql.connect(dbSettings, function(err) {
if(err) {
console.log(err);
}
});
return pool;
} catch (error) {
console.log(error);
}
}
products.controller.js
import {getConnection} from '../database/connection';
export const getProducts = async (req, res) => {
const pool = await getConnection();
const result = await pool.request().query('SELECT * FROM Products');
console.log(result);
res.json('products');
};
I'm asking help as I'm trying to get 2 different sets of data from a mysql db. I've written 2 separate functions using promisify. Unfortunately when I execute this node file only the first function gets executed and shown in the console. After some debugging I think it's await query(...) the cause of this problem. After this query (the one inside getSources() ) is executed, the process is suspended and I've got to terminate it. I also tried using mysql2 and moving con.end() to a different line unsuccesfully. Of course any help we'll be appreciated.
import mysql from 'mysql';
import { promisify } from 'util';
import express from 'express';
import path from 'path';
const sql = "SELECT `id` FROM `probes` WHERE `country`= ?";
const sql1 = "SELECT `fqdn` FROM `anchors` WHERE `country`= ?";
let sources = []; //sources
let targets = []; //targets
const app = express();
const __dirname = path.resolve();
app.use(express.urlencoded( {extended: true} ));
app.use(express.static(__dirname));
const con = mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'probes&anchors'
});
const query = promisify(con.query).bind(con);
const getSources = async (from) => {
console.log("I'm in getSources");
con.connect((err)=>{
if(err){
console.log("Connection not proper");
}else{
console.log("connected");
}
});
await query(sql, [from], (err, rows) => {
console.log("error in query: "+ err);
if (err) throw err;
rows.forEach((v) => {
sources.push(v.id);
});
console.log(sources);
con.end(err => {
if(err) console.log(`${err.toString()}`)
console.log('con ended')
});
});
};
const getTargets = async (to) => {
console.log("I'm in getTargets");
con.connect((err)=>{
if(err){
console.log("Connection not proper");
}else{
console.log("connected");
}
});
await query(sql1, [to], (err, rows) => {
console.log(err);
if (err) throw err;
rows.forEach((v) => {
targets.push(v.fqdn);
});
con.end(err => {
if(err) console.log(`${err.toString()}`)
console.log('con ended')
});
});
};
app.post('/', async function(req,res){
await getSources(req.body.from_country);
await getTargets(req.body.to_country);
console.log(sources);
console.log(targets);
res.send("Loaded");
});
app.get('/', (req, res) => res.send('Hello World! From Node.js'));
app.listen(8000, () => console.log('Example app listening on port 8000!'));
I'm using redis for the first time, and I can't quite figure out why my middleware 'cache' function is breaking my code? It works great without it, displays in the browser, if I go to my terminal and check for a key value pair it works great.
Here is my setup:
const express = require("express");
const redis = require("redis");
const axios = require("axios").default;
const PORT = process.env.PORT || 5000;
const REDIS_PORT = process.env.PORT || 6379;
const client = redis.createClient(REDIS_PORT);
client.connect();
const app = express();
function setResponse(username, repos) {
return `<h2>${username} has ${repos} Github repos</h2>`;
}
// make req to github
async function getRepos(req, res, next) {
try {
console.log("fetching data...");
const { username } = req.params;
const response = await axios.get(
`https://api.github.com/users/${username}`
);
const data = response.data;
const repos = data.public_repos;
// set to redis
client.set(username, repos);
res.send(setResponse(username, repos));
} catch (err) {
console.log(err);
res.status(500);
}
}
// Cache middleware
function cache(req, res, next) {
const { username } = req.params;
client.get(username, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
}
app.get("/repos/:username", cache, getRepos);
app.listen(5000, () => {
console.log(`App listening on port ${PORT}`);
});
Any advice would be much appreciated!
Your cache function
function cache(req, res, next) {
const { username } = req.params;
client.get(username, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
}
uses node redis 3 "logic" so it's hanging
redis 4 is promise led, so you need to use async/await or .then/.catch
So something like this should work for the .then/.catch approach
// Cache middleware
function cache(req, res, next) {
console.log('caching for', req.params);
const { username } = req.params;
client.get(username)
.then((data) => {
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
})
.catch(err => {
if (err) throw err;
});
}
This will solve your initial problem of "why it's getting stuck"
My /chat route works well through Post method with validation with Joi schema but when I send request through Get method, it show Sending Request and continue loading...
My index.js file:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const chat = require('./db/ChatModel');
const app = express();
app.use(bodyParser.json());
app.get('/chat', (req, res) => {
chat.getAllMessages().then( (messages) => {
res.json(messages);
});
});
app.post('/chat', (req, res) => {
console.log(req.dody);
chat.createMessages(req.body).then((message) => {
res.json(message);
}).catch( (error) => {
res.status(500);
res.json(error);
});
});
const port = process.env.PORT || 8888;
app.listen(port, () => {
console.log(`Listening on port ${port}...`);
});
In connection.js I coded this
const monk = require('monk');
const connectionString = 'localhost/chatboard';
const db = monk(connectionString);
module.exports = db;
And ChatModal.js has the following code
const Joi = require('joi');
const db = require('./connection');
const schema = Joi.object().keys({
username: Joi.string().alphanum().min(4).max(16).required(),
subject: Joi.string().required(),
message:Joi.string().max(300).required(),
imgUrl: Joi.string().uri({
scheme: [ // https://github.com/hapijs/joi/blob/v14.3.1/API.md#stringurioptions
/https?/
]
})
});
const chat = db.get('chat');
function getAllMessages() {
return chat.find();
};
function createMessages(message) {
const result = Joi.validate(message, schema);
if (result.error == null) {
message.created = new Date();
return chat.insert(message);
} else {
return Promise.reject(result.error);
}
}
module.exports = {
createMessages,
getAllMessages
};
I can't understand why getAllMessages() doesn't work and postman continue loading when Get request applied like this http://prntscr.com/s0d9c5
ChatModal.js
function getAllMessages() {
try {
return chat.find();
} catch (err) {
return next(err);
}
index.js
app.get('/chat', (req, res, next) => {
try{
data = chat.getAllMessages()
} catch (err) {
return next(error);
}
res.json(data);
});
User try-catch in the ChatModal.js and also index.js then you can understand what is actual error, like bellow:
ChatModal.js
function getAllMessages() {
try {
chat.find();
} catch (err) {
return next(err);
}
I think, may be your data, i mean message list data so weight, in this case you get all message,res.json(messages); json method have long time to parse messages data
I'm trying to use connection from a connection.js file and use it in different file webFrontend.js using exports object. Now what I get on running server is:
{
"Result": "undefinedThis is result"
}
That means connection is not defined. Why is it happening? connection is working fine if getConnection is created in same (webFrontend.js) file, but the problem is when I use getConnection in same exports function in connection.js hence the connection not defined error:
Here are 2 necessary files (routes file has no problem) that explains what I'm doing:
connection.js
var mysql = require('mysql');
exports.connExport = function () {
var connectionPool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'rockcity_followme'
});
if(connectionPool) {
connectionPool.getConnection(function (err, connection) {
if (err) {
return err;
} else {
return connection;
}
});
}else{
var abc="return error";
return abc;
}
}
webFrontend.js
var connObj=require('../Routes/connection.js');
var connection=connObj.connExport();
exports.getIndivRecords= function(req, res, next){
res.send({
Result: connection+"This is result"
});
return next();
};
No need for the .js file extension, it's automagically added for you.
The code below uses standard error-first callbacks
webFrontend.js
var connection = require('../Routes/connection');
exports.getIndivRecords = function(req, res, next){
// connection takes a standard error-first callback
connection(function(err, conn){
if (err) {
// Handle the error returned
console.log(err);
}
// The database connection is available here as conn
console.log( "Connection:" + conn);
// presumably you want to do something here
// before sending the response
res.send({
Result: conn + "This is result"
});
});
return next();
};
connection.js
var mySQL = require('mysql');
var connectionPool = mySQL.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'rockcity_followme'
});
var getConnection = function (cb) {
connectionPool.getConnection(function (err, connection) {
// pass the error to the callback
if (err) {
return cb(err);
}
cb(null, connection);
});
};
module.exports = getConnection;
First of all #Dan Nagle was right no need of .js
Second You are getting the connection undefinded because still the method doesnt returned with result.
Use promise to call your Connection.js method
Your node is single threaded async execution,
He doest wait for the method to return a result
1) Problem with your javascript is that
var connection=connObj.connExport();
in Creation stage connection was defined by javascript as undefined and as
connObj.connExport(); as still not returned with answer
it executed this function in which connection was undefined
exports.getIndivRecords= function(req, res, next){
res.send({
Result: connection+"This is result"
});
Use promise read this first so you can understand something about promise and callback if you are unable to solve than comment i will play with it.But first you try.Thanku
Understanding promises in node.js
Ok Try This I have used promise here
var connObj = require('../Routes/connection');
connObj.connExport().then(
function (connection) {
exports.getIndivRecords = function (req, res, next) {
res.send({
Result: connection + "This is result"
});
return next();
};
}).catch(function (err) {
res.status(400).send(err);
return;
});
var mysql = require('mysql');
exports.connExport = function () {
return new Promise(function (fulfill, reject) {
var connectionPool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'rockcity_followme'
});
if (connectionPool) {
connectionPool.getConnection(function (err, connection) {
if (err) {
return reject(err);
} else {
return fulfill(connection);
}
});
} else {
var abc = "return error";
return reject(abc);
}
});
}