I do a select statement on sqlite3 in node.js. I'd like to have the result in the variable "data" which is defined outside the sqlite code block but it stays empty. Within the sqlite code block the data variable has the correct value. Does anybody know what I'm doing wrong?
Thank you.
/* Client connects via socket.io */
io.on('connection', function(client) {
console.log('Client connected');
/* Client needs data... */
client.on('needData', function(fields) {
var data = [];
var sql_stmt = "SELECT ...";
if(fs.existsSync(db_file)) {
try {
var db = new sqlite3.Database(db_file);
db.all(sql_stmt, function(err, all) {
data = all;
console.log(data); //--> data has valid values
});
db.close();
console.log(data); //--> data is empty
}
catch(e) {
console.log("Error with database. Error: ", e);
}
}
else {
console.log("Database file not found.");
}
client.emit('data', data);
});
});
It happening just because of asynchronous nature of Node.js you can handle it with by promises
I recommend to use waterfall method of async module
var async=require('async');
/* Client connects via socket.io */
io.on('connection', function(client) {
console.log('Client connected');
/* Client needs data... */
client.on('needData', function(fields) {
async.waterfall([function(next) {
var sql_stmt = "SELECT ...";
if (fs.existsSync(db_file)) {
try {
var db = new sqlite3.Database(db_file);
db.all(sql_stmt, function(err, all) {
next(null,all)
});
db.close();
} catch (e) {
console.log("Error with database. Error: ", e);
next();
}
} else {
console.log("Database file not found.");
next();
}
}], function(err, data) {
if (!err) {
client.emit('data', data);
}
})
});
});
Related
Im using Socket.io and Rethink DB to push realtime data on Node.js.
Subscribing to the stream works but when the user disconnects I can figure out how to unsubscribe to the rethink db.
Here's my code:
Part of app.js:
// Adding socket.io
app.io = require('socket.io')();
var feed;
// On connection to the socket, just invoking the function.
app.io.on('connection',function(socket) {
console.log('Client connected...');
feed = require('./feed')(socket);
socket.on('disconnect', function() {
console.log('Got disconnect!');
# Here I'd like to unsubscribe
});
});
feed.js:
var r = require('rethinkdb');
var dbConfig = require('./config/database');
module.exports = function(socket) {
var connection = r.connect(dbConfig)
.then(function (connection) {
r.db('Minicall').table('Message').changes().run(connection,function(err,cursor) {
if(err) {
console.log(err);
}
cursor.each(function(err,row) {
console.log(JSON.stringify(row));
if(Object.keys(row).length > 0) {
console.log("send");
socket.emit("msgFeed",{"timestamp" : row.new_val.timestamp, "message" : row.new_val.message ,"ric" : row.new_val.ric});
}
});
});
});
};
So, how can I stop the subscribing (connection.stop()) when socket.on('disconnect') gets called? Probably a easy solution since I'm totally new to node and js.
You can have more than one event listener to an event, so in your cursor you'll add a disconnect event listener that can call cursor.close():
r.db('Minicall')
.table('Message')
.changes()
.run(connection, function(err, cursor) {
if(err) {
console.log(err);
}
cursor.each(function(err,row) {
console.log(JSON.stringify(row));
if(Object.keys(row).length > 0) {
console.log("send");
socket.emit("msgFeed",{"timestamp" : row.new_val.timestamp, "message" : row.new_val.message ,"ric" : row.new_val.ric});
}
});
socket.on('disconnect', function() {
cursor.close();
});
});
Im trying to save a json object in my database. The save() function is not being called but and the json object is never saved.
Help me figure out the problem.
I guess it's a connection problem with mongoose.
Here is my code..
var config = require('../config');
var user = require('../user');
api.post('/addUser',function(req,res) {
var userID;
//creating a sample user under Model collection User.. so this becomes a document!!
console.log("addition of new user api hit!!");
//sending a query to retrieve the no of users served
MongoClient.connect(dbURL, function (err, db) {
var UserCountCursor = db.collection("ourusers").find({"docName": "userCount"}).limit(1);
UserCountCursor.each(function (err, doc) {
if (err)
console.log("did not get the count");
else
// var countString= JSON.stringify(doc);
//var docJson=JSON.parse(countString);
console.log("the json content is:" + doc.iparkoUserCount);
//increase the user count by 1 in the db.
var incCount = parseInt(doc.iparkoUserCount) + 1;
console.log("no of userrs:" + incCount);
// making an userId
userID = "ipkoID_C" + incCount.toString();
//updating using MOngoClient
db.collection("ourusers").update({"docName": "userCount"}, {$set: {"iparkoUserCount": incCount}});
console.log("the user count in the db has been updated!!");
console.log("generated id for this guy is:" + userID);
if (userID != null) {
console.log("calling the save function");
//closing the mongoclient connection
db.close();
signUpUser(userID);
}
});
});
function signUpUser(userIDD) {
var me = new user({
name: req.body.new_name,
password: req.body.new_pswd,
username: req.body.new_username,
phno: req.body.new_phn,
userId: userIDD
});
console.log("the obj ::" + JSON.stringify(me));
console.log("obj created and ready to be stored");
//connecting to the db using mongoose
mongoose.connect(config.database, function (err) {
if (err)
console.log("The error is :"+err);
else {
console.log("WE ARE CONNECTED USING MONGOOSE");
//saving the sample user document
me.save(function (err) {
console.log("in the save func");
if (err) throw err;
else {
console.log('User saved Successfully!!!!!');
res.json({
'whatStatus': 'user saved in the database!!',
'userID': userIDD
});
mongoose.connection.close();
}
});
}
});
}
});
My console logs::
addition of new user api hit!!
the json content is:143
no of userrs:144
the user count in the db has been updated!!
generated id for this guy is:ipkoID_C144
calling the save function
the obj ::{"name":"Abhi","password":"jio","username":"abhijio","phno":"45142545","userId":"ipkoID_C144","_id":"583295bfa0f9f8342035d3b9"}
obj created and ready to be stored
C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\utils.js:98
process.nextTick(function() { throw err; });
^
TypeError: Cannot read property 'iparkoUserCount' of null
at C:\Users\shivendra\WebstormProjects\iParko\routes\RegisteredParkingLots.js:76:57
at handleCallback (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\utils.js:96:12)
at C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:742:16
at handleCallback (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\utils.js:96:12)
at C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:676:5
at handleCallback (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\node_modules\mongodb-core\lib\cursor.js:156:5)
at setCursorDeadAndNotified (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\node_modules\mongodb-core\lib\cursor.js:496:3)
at nextFunction (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\node_modules\mongodb-core\lib\cursor.js:588:12)
at Cursor.next [as _next] (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\node_modules\mongodb-core\lib\cursor.js:681:3)
at nextObject (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:673:8)
at Cursor.next (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:262:12)
at _each (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:738:10)
at C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:746:7
at handleCallback (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\utils.js:96:12)
at C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\lib\cursor.js:676:5
at handleCallback (C:\Users\shivendra\WebstormProjects\iParko\node_modules\mongodb\node_modules\mongodb-core\lib\cursor.js:156:5)
Process finished with exit code 1
You seem to be opening the db connection twice one with mongoose.connect and another one with mongoose.connection.open(). That's why you are getting error.
Try using this with just one connection as below.
mongoose.connect(config.database, function(err, db) {
//var dbcon=mongoose.connection.open();
//dbcon.on('error',function(){console.log('connction error:')});
//dbcon.once('open',function(){
if(err) {
console.log(err);
} else {
console.log("WE ARE CONNECTED USING MONGOOSE");
//saving the sample user document
me.save(function (err) {
console.log("in the save func");
if (err) throw err;
else {
console.log('User saved Successfully!!!!!');
res.json({
'whatStatus': 'user saved in the database!!',
'userID': userIDD
});
//mongoose.connection.close();
}
});
}
});
Inside your UserCountCursor.each(...) loop, after checking for err you should also check for doc. So where you have this:
UserCountCursor.each(function (err, doc) {
if (err)
console.log("did not get the count");
else
// var countString= JSON.stringify(doc);
//...
})
do this instead:
UserCountCursor.each(function (err, doc) {
if (err){
console.log("did not get the count");
}else if(doc){
// var countString= JSON.stringify(doc);
//...
}
})
Then you will avoid the Cannot read property 'iparkoUserCount' of null error and you'll get into your save() function.
let's first see the code before I start talking:
var sqlDb = require("mssql");
var settings = require("../settings");
exports.executeSql = function (sql, callback) {
var conn = new sqlDb.Connection(settings.dbConfig);
console.log('db.js Send sql-query');
console.log(" ");
conn.connect()
.then(function () {
var req = new sqlDb.Request(conn);
req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log("here it breaks", err);
callback(null, err); //type error: undefined is not a function
})
})
.catch(function (err) {
console.log(err);
callback(null, err);
}); //
};
This function recieves an sql statement and a callback function. When I run the code I get [Type Error: undefined is not a function].
When I comment out the callback(recordset) it doesnt do anything (no error but also nothing else). So I think that the callback is simply not recognized as if it were out of scope. The weird part is, that the error object is transferred back via the same callback function and that seems to work.
The settings.dbConfig looks like this:
exports.dbConfig = {
user: "username",
password: "pwd",
server: "SERVERNAME", // not localhost
database: "DB-Name",
port: 1433
};
I am quite depressed by now. Would someone be so kind as to have a look at my code? I simply don't see the mistake.
Thank you
EDIT:
I call executeSql like this:
var db = require("./db");
var sql = "SELECT * FROM myTable";
db.executeSql(sql, function(data, err) {
if (err) {
console.log(" Internal Error: error connecting Database", err);
} else {
console.log("success", data);
}
});
I am attempting to use NodeJS with the Tedious (http://pekim.github.io/tedious/) sql server plugin to make multiple database calls. My intent is to:
1. Open a connection
2. Start a transaction
3. Make multiple database (stored procedure) calls, which will not return any data.
4. Commit transaction (or roll back on error).
5. Close connection
Here is an example .js file, (without using a transaction) for NodeJS where I am attempting to make multiple database calls and it is failing with the error "Requests can only be made in the LoggedIn state, not the SentClientRequest state." Nothing I try resolves this issue.
Does anyone know how to resolve this?
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var config = {
userName: 'login',
password: 'password',
server: '127.0.0.1',
options: { rowCollectionOnDone: true }
};
var max = 1;
for (var i = 0; i < max; i++) {
var connection = new Connection(config);
function executeStatement() {
request = new Request("select 42, 'hello world'", function (err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', function (columns) {
columns.forEach(function (column) {
console.log(column.value);
});
});
request.on('doneInProc', function (rowCount, more, rows) {
});
request.on('doneProc', function (rowCount, more, rows) {
console.log('statement completed!')
connection.execSql(request);
});
request.on('returnStatus', function (status) {
console.log('statement completed!')
});
connection.execSql(request);
}
connection.on('connect', function (err) {
// If no error, then good to go...
executeStatement();
});
}
console.log('Done!');
You're trying to execute a statement on a connection that is not established. You're missing an error handler before you call executeStatement.
connection.on('connect', function (err) {
if (err) {
console.log(err); // replace with your code
return;
};
// If no error, then good to go...
executeStatement();
});
Edit:
How to execute multiple statements in a transaction in serial:
var statements = ["select 1", "select 2", "select 3"];
var transaction = new sql.Transaction(connection);
transaction.begin(function(err) {
// ... error checks
async.mapSeries(statements, function(statement, next) {
var request = new sql.Request(transaction);
request.query(statement, next);
}, function(err, results) {
// ... error checks
transaction.commit(function(err, recordset) {
// ... error checks
console.log("Transaction commited.");
});
});
});
You should use tedious connection pools to create a pool of multiple connections.
For node js, a npm module is available at : https://www.npmjs.com/package/tedious-connection-pool
For every new value inside for loop you can acquire a new connection and use connection.reset on doneInProc event.
The case which you have been doing is performing 1st iteration of for loop correctly(LoggedIn State) and as you have proceeded without closing or releasing the connection you are using same connection object (SentClientRequest state).
Hence the same object is at final state when the code reaches second iteration of for loop.
Hope it resolves your issue
you can use Tedious Connection pools https://github.com/pekim/tedious-connection-pool
As #zevsuld and #mannutech said, tedious-connection-pool will enable multiple connections, and prevent erring out when simultaneous requests come into your server.
Below is a generic example that allows you to write multiple queries within one connection pool, and expose them for use in your api. I'm just adding this in case others come along who are trying to accomplish this type of implementation.
const ConnectionPool = require('tedious-connection-pool');
const path = require('path');
require('dotenv').config({
path: path.join(__dirname, '../../.env')
})
let Request = require('tedious').Request;
let poolConfig = {
min: 10,
max: 50,
log: true
}
let connectionConfig = {
userName: process.env.user,
password: process.env.password,
server: process.env.server
};
//create the pool
let pool = new ConnectionPool(poolConfig, connectionConfig);
pool.on('error', function(err) {
console.error(err);
});
// At this point in the code, we have established a connection pool. If you run node, you'll see it log out all then connections to your database.
// Let's add some methods which your server might use in fulfilling requests to various endpoints.
let query1 = (cb, res, query) => {
// acquire a connection:
pool.acquire(function(err, connection) {
if (err) {
console.error(err);
return;
} else {
// form your query
let sql_query = `SELECT column1, colum2 from TABLE WHERE column1 LIKE '${query.param}%%' ORDER BY column1 ASC`
// use the connection as usual:
request = new Request(sql_query, (err, rowCount) => {
if (err) {
console.log(err);
return;
} else {
// console.log('rowCount:', rowCount);
}
//release the connection back to the pool when finished
connection.release();
});
let records = [];
request.on("row", function(columns) {
let rowArray = [];
columns.forEach(function(column) {
rowArray.push(column.value);
});
records.push(rowArray);
});
request.on("doneInProc", function() {
cb(records, res);
});
// lastly exectue the request on the open connection.
connection.execSql(request);
}
});
};
let query2 = (cb, res, query) => {
// acquire a connection:
pool.acquire(function(err, connection) {
if (err) {
console.error(err);
return;
} else {
// form your query
let sql_query = `SELECT column3, colum4 from TABLE2 WHERE column3 LIKE '${query.param}%%' ORDER BY column3 ASC`;
// use the connection as usual:
request = new Request(sql_query, (err, rowCount) => {
if (err) {
console.log(err);
return;
} else {
// console.log('rowCount:', rowCount);
}
//release the connection back to the pool when finished
connection.release();
});
let records = [];
request.on("row", function(columns) {
let rowArray = [];
columns.forEach(function(column) {
rowArray.push(column.value);
});
records.push(rowArray);
});
request.on("doneInProc", function() {
cb(records, res);
});
// lastly exectue the request on the open connection.
connection.execSql(request);
}
});
};
// Let's expose these two functions to the rest of your API:
module.exports = {
query1,
query2
}
Im using connect-domain and connect-redis. Below code checks for redis cache in Redis database.
function redis_get(key, req, res) {
var redisClient = redis.createClient();
redisClient.get(redisKey, function (err, data) {
if (err) {
console.log("Error in RedisDB");
}
else if (data == null) {
// Calling external function
}
else {
// Calling external function
}
redisClient.quit(); // Not working
});
}
When cache is not avaiable Im calling external function. I want redis connection to be closed once the cache check has been done.
redisClient.quit() // Not working
Any help on this will be really helpful.
Thanks
Below code is working fine without any problem.So check your status reply in the quit method if you get status as 'OK' means that method is working fine.
var redis=require('redis');
var redisClient = redis.createClient();
redisClient.get('name', function (err, data) {
if (err) {
console.log("Error in RedisDB");
}
else if (data == null) {
console.log('null');
}
else {
console.log(data);
}
redisClient.quit(redis.print);
});