I'm new with NODE and I'm trying this code:
require('../../constants.js');
function dbConnect() {
var mysql = require('mysql');
var connection = mysql.createConnection({
host : DB_HOST,
database : DB_NAME,
user : DB_USER,
password : DB_PASS,
});
connection.connect(function(err) {
console.log("Database is connected ...");
});
return connection;
}
function dbDisconnect(connection) {
connection.end();
console.log("Closing DB Connection");
}
function findPlayer(surname) {
var connection = dbConnect();
console.log("Finding -> " + surname);
var query = 'SELECT * FROM players WHERE surname = "' + surname + '"';
connection.query(query, function(err, rows, fields)
{
if (err) throw err;
for (var i in rows) {
console.log('Players: ', rows[i].surname);
}
});
dbDisconnect(connection);
}
exports.findPlayer = findPlayer;
After that, I've a laucher file:
require('./constants.js');
var aar = require('./libs/DBManager.js')
console.log('Loading DBManager');
var player = aar.findPlayer('Potter');
console.log(player);
Correct workflow is:
Loading DBManager
Database is connected...
Finding -> Potter
Players: Potter
Closing DB Connection
However the result is:
Loading DBManager
Finding -> Potter
Closing DB Connection
undefined
Database is connected...
Players: Potter
What's my wrong? Is some callback issue?
You are closing your connection before your query is for sure done.
you should put the dbDisconnect(connection); after the end of the query but inside the callback.
connection.query(query, function(err, rows, fields)
{
if (err) throw err;
for (var i in rows) {
console.log('Players: ', rows[i].surname);
}
dbDisconnect(connection);
});
also the findPlayer is not returning anything, so the console.log(player); will be undefined
Javascript is Async in nature, it doesn't wait for I/O operations. Any network call including request to connect to a DB comes under I/O operations.
The problem is that you are requesting a DB connection and before it is returned, you are making call to get data for players. I suggest you pass a callback method to the
dbConnect(callback)
And in that callback, you pass the query or operation you want to execute:
Create a callback method that contains the code to retrieve the players information
Call dbConnect() to establish the connection to DB and pass the callback as an argument
After connection is established, execute the callback
After you are done, you can close the connection, but make sure the code to close the connection, is with in the callback and is executed only after you received the data from Db
On the contrary if you are comfortable with ORM, i suggest you try Sequelize, it abstracts out the requirement to create and disconnect connections with DB, so you can focus on your crud operations.
Related
After receive message from client, I have to connect db(mysql) and save data and need to response the result to client and inform to other(admin) client.
So I need to get current socket client and special client(admin) from the socket list.
Is it possible to get current socket outside of wss connection block?
Thanks.
const WebSocketServer = require('ws');
// Creating a new websocket server
const wss = new WebSocketServer.Server({ port: 8080 });
const clients = new Map();
// Creating connection using websocket
wss.on("connection", ws => {
console.log("new client connected");
client_id = Date.now();
clients.set(client_id, ws);
// sending message
ws.on('message', function(message) {
//wss.broadcast(JSON.stringify(message));
console.log('Received: ' + message);
BuyCoin(message);
//console.log()
});
ws.on("close", () => {
console.log("the client has connected");
});
ws.onerror = function () {
console.log("Some Error occurred")
}
// ws.send('You successfully connected to the websocket.');
});
function BuyCoin(strValue){
const req_info = JSON.parse(strValue);
console.log(req_info.user_id)
console.log('betting!');
var sql = 'SELECT * from users where id = ? LIMIT 1'
connection.query(sql, req_info.user_id, (ws)=>{
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
}
}
You have several options:
#1: You can put the BuyCoin function logic inside the ws scope to make it a local function that is in scope of the ws variable for the current connection like this:
const WebSocketServer = require('ws');
// Creating a new websocket server
const wss = new WebSocketServer.Server({ port: 8080 });
const clients = new Map();
// Creating connection using websocket
wss.on("connection", ws => {
console.log("new client connected");
client_id = Date.now();
clients.set(client_id, ws);
// sending message
function BuyCoin(strValue) {
const req_info = JSON.parse(strValue);
console.log(req_info.user_id)
console.log('betting!');
var sql = 'SELECT * from users where id = ? LIMIT 1'
connection.query(sql, req_info.user_id, (ws) => {
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
}
ws.on('message', function(message) {
//wss.broadcast(JSON.stringify(message));
console.log('Received: ' + message);
BuyCoin(message);
//console.log()
});
ws.on("close", () => {
console.log("the client has connected");
});
ws.onerror = function() {
console.log("Some Error occurred")
}
// ws.send('You successfully connected to the websocket.');
});
#2: You can pass the ws value to your BuyCoin() function as an argument by just changing the function call from this:
BuyCoin(message);
to this:
BuyCoin(ws, message);
And, then changing your function declaration from this:
function BuyCoin(strValue) {...}
to this:
function BuyCoin(ws, strValue) {...}
Is it possible to get current socket outside of wss connection block?
No, there really is no such thing as the current socket. When using asynchronous code in nodejs, lots of different pieces of code can be "in-flight" at the same time so there is no global sense of the current socket. Instead, you have manage data specific to your current operation either by using scope, by passing as an argument or by setting as a properties on some other object that is passed as an argument. Since there is no natural object that BuyCoin() already has access to here that is specific to the user with the activity, then that leaves the first two options (using scope and passing as an argument).
FYI, this code looks a bit problematic because you're allowing the webSocket to send in the user_id that will be operated on without any visible authentication. That exposes you to rogue sockets that can pretend to be users that they aren't.
Also, it doesn't appear you have code that removes webSockets from the clients Map object when they disconnect so that Map object will just get larger and larger and contain lots of dead connections.
Another thing that needs fixing is that your connection.query() code is declaring a callback that does nothing but return another function and it tried to make up a value of ws that would never actually be passed. That function you create inside the callback is never called. Change from this:
connection.query(sql, req_info.user_id, (ws) => {
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
to this:
connection.query(sql, req_info.user_id, (err, rows, fields) => {
//console.log("ix="+ix);
ws.send(rows[0]);
});
And, combine that with one of the above two solutions to get access to the ws value.
I'm making a simple node.js webapp for inserting data into a database with a condition - when there's two instances with the same time attribute, the insert query isn't called and you get redirected to a simple html page with a message that you have to pick another time.
My question is, how can I redirect from a block of code belonging to query? or is there another way to let user know that he has to pick another time?
app.post('/', function(req, resp) {
try {
var name = req.body.name;
var date = req.body.date + " " + req.body.time;
var phone = req.body.phone;
var spz = req.body.spz;
var typeOfProblem = req.body.typeOfProblem;
con.query(("SELECT COUNT(*) AS datecheck FROM `objednani` WHERE datetime = '"+ date +"'"), function(err, result){
if (err) throw err;
if(result[0].datecheck > 1){
console.log("preplneno"); // THIS IS THE POINT WHERE I WANT TO REDIRECT THE USER
} else {
con.query(("INSERT INTO objednani (name, datetime, phone, spz, typeofproblem) " + "VALUES ('"+name+"','"+date+"','"+phone+"','"+spz+"','"+typeOfProblem+"')"), function (err, result) {
if (err) throw err;
console.log("uspech");
});
}
});
} catch (err) {
resp.redirect('/fail');
}
});
You can call resp.redirect('/fail'); inside your query block, or anywhere in function(req, resp) function. You don't need to throw and catch.
As another suggestion: you can try parameter embedding for your sqls. otherwise you can be subject to sql injection attacks.
I have a MongoDB instance and two JavaScript services running on a Linux server. The first service, moscaService.js, listens to MQTT topics on the server, and records what is sent in a MongoDB collection. The second service, integrationService.js, runs every second, reading data on the same MongoDB collection and, if there's a new register (or more), sends it to Ubidots.
The problem is that both services work on the same IP/port: localhost:27017; and, if there ever is an occasion in which both of them are active simultaneously (say, moscaService.js is recording something and then the integrationService.js tries to connect), there will be a connection error and the service will restart.
Here are the connection parts of both services:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://127.0.0.1:27017/myGateway';
//integrationService.js
var job1 = new CronJob('*/1 * * * * *', function() {
MongoClient.connect(url, function(err, db) {
if(err != null) {
logger.error({message: 'Connection error: ' + err});
process.exit(0);
} else {
executeService();
}
function executeService() {
// execution block
}
});
}, null, true, timeZone);
//moscaService.js
server.on('published', function(packet, client) {
//the packet is read here
MongoClient.connect(url, function(err, db) {
if(err != null) {
logger.error({message: 'Connection error: ' + err});
process.exit(0);
} else {
executeService();
}
function executeService() {
// execution block
}
});
});
What I need is a way to properly handle the err instead of just exiting the service, because if there are new messages being published while the service is restarting, they will be lost. Something like testing if the port is open before connecting, or open a different port.
I tried creating another instance of MongoDB on a different port, in order to have each service listen to one, but it looks like Mongo locks more than one instance if it's trying to connect to the same database.
The code snippets here are just a small part; if anyone needs more parts to answer, just say so and I'll add them.
I have made an alteration and it solved this issue. I altered the code in a way that integrationService connects to MongoDB before starting the CronJob; that way, it only connects once and it keeps the connection alive.
Here's the connection part of the code:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://127.0.0.1:27017/myGateway';
//integrationService.js
MongoClient.connect(url, function(err, db) {
var job1 = new CronJob('*/1 * * * * *', function() {
if(err != null) {
logger.error({message: 'Connection error: ' + err});
process.exit(0);
} else {
executeService();
}
function executeService() {
// execution block
}
}, null, true, timeZone); // end CronJob
}); // end MongoClient.connect
Since this has solved the problem, I've left the err treatment as is was (although a more elegant way to treat it is still desirable).
Solving the problem on integrationService has solved it on moscaService as well, but I plan to make the same alteration on the second service too.
I'm trying to make a simple task.
In the first place, on client side, i'm sending data to server and then i insert these data into my mongodb database.
Then i try to get count of clients from my database.
var express = require('express');
var MONGO_URL = "mongodb://localhost:27017/mydatabase";
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
mongo = require('mongodb').MongoClient,
fs = require('fs');
var countUserSuscribed =0;
//here i insert data
/* Connection events */
io.on('connection', function (client) {
console.log("User connected");
client.on('InsertNewUser', function (newUser) {
console.log("we ar in InsertNewUser event");
//////////////////////////////////////////////////////////
mongo.connect(MONGO_URL, function (err, db) {
console.log("we are connected to mongodb");
var Users = db.collection('User');
console.log("on crée la collection et on fait l'ajout");
Users.insert({ player: myP }, function (err, o) {
if (err) { console.warn(err.message); }
else { console.log("user inserted into db: user"); }
});
});
})
});
//GET COUNT USER
console.log("here we get count user");
mongo.connect(MONGO_URL, function (err, db) {
countUserSuscribed = Users.count();
console.log("we got " + countUserSuscribed + " user in mongoDB");
});
With this code i can create collections and insert documents but the count function doesn't work and i didn't find much explanations on npm documentation.
Is it possible to use others mongodb functions than insert and collection with socket.io-mongodb ?
If it is, can someone give an example or explain me how to use it?
The count function works but is async function and takes a callback.
here's the fix:
countUserSuscribed = Users.count(function (err,c) { console.log(c) });
https://www.npmjs.com/package/mongodb-autoincrement consider using that. It keeps a track of all inserted document. Plus it has a handy feature to get the next count. Example let's say you inserted two records. If you call next count it will show 3. There fore to get the total documents inserted call get next count - 1. Make sense?
Sorry here is the correct one. https://www.npmjs.com/package/mongoose-auto-increment
I am using socket.io in my Express.js web app to open sockets for clients that are listening for events that call a SQL query. The server socket looks like this:
socket.on('updates', function(PEMSID){
setInterval(function(){
gps_helper.get_gps(PEMSID, function(data){ //query GPS table for marker coordinates
socket.emit('message', {message: data});
});
}, 10000);
So, every ten second the get_gps() function is being called that does long polling to check if any new records have been added to a table. The get_gps() function looks like this:
exports.get_gps = function(PEMSID, callback) {
var sql = require('msnodesql');
var connStr = "Driver={SQL Server Native Client 11.0};Server=myHost,1433;Database=myDB;UID=Username;PWD=Password;";
var mQuery = "EXEC Z_CoordsByPEMS '" + PEMSID + "'";
sql.open(connStr, function(err,conn){
if(err)
return console.error("Could not connect to sql: ", err);
conn.query(mQuery,function(err,results){
if (err)
return console.error("Error running query: ", err);
callback(results); //return query results
});
});
}
The problem I'm encountering is the get_gps() is opening a new connection to the SQL db everytime it polls for any updates. This is obviouslly causing insane overhead on the server hosting the db and needs to be changed, as the server's CPU eventually reaches maximum capacity and all future queries time out. I'm using the module msnodesql to do the SQL db tasks, but it doesn't appear there's a close() function in the API to close existing connections. I think I'll need to create one global connection and then have all new sockets reference that in order to do their long polling. I'm unsure however how to set up the global connection, if it's even possible, given the asynchronous nature of Express.js/node.js.
Currently, you're creating a new SQL connection for each query your send. Instead, you've said you want to have one SQL connection per socket.io connection. Create the SQL connection whenever you get an updates request (assuming you only get this message once per socket.io connection):
socket.on('updates', function(PEMSID){
var sql = require('msnodesql');
// open a new socket for each `updates` message
sql.open(connStr, function(err,conn){
if(err) { return console.error("Could not connect to sql: ", err); }
// when the connection is made, start the interval
setInterval(function(){
// each interval, get_gps, and pass `conn` as an argument
gps_helper.get_gps(conn, PEMSID, function(data){ //query GPS table for marker coordinates
socket.emit('message', {message: data});
});
}, 10000);
});
});
Then your get_gps function will accept a conn argument:
exports.get_gps = function(conn, PEMSID, callback) {
var connStr = "Driver={SQL Server Native Client 11.0};Server=myHost,1433;Database=myDB;UID=Username;PWD=Password;";
var mQuery = "EXEC Z_CoordsByPEMS '" + PEMSID + "'";
// no need to open `conn`; it's already made
conn.query(mQuery,function(err,results){
if (err)
return console.error("Error running query: ", err);
callback(results); //return query results
});
}
If you want one global SQL connection, simply move the sql.open call even higher:
// create conn outside of the socket.io message callback
sql.open(connStr, function(err,conn){
if(err) { return console.error("Could not connect to sql: ", err); }
io.sockets.on("connection", function(socket) {
socket.on('updates', function(PEMSID){
setInterval(function(){
gps_helper.get_gps(conn, PEMSID, function(data){ //query GPS table for marker coordinates
socket.emit('message', {message: data});
});
}, 10000);
});
});
});