Why isn't my Q promise working? - node.js

I'm new to promises and Q, and I'm trying to convert a route that uses query in node-mysql. Here are excerpts from my code:
var Q = require('q');
// connection defined elsewhere
router.get('/', function(req, res) {
var query = Q.denodeify(connection.query);
var promise = query("-- query ommitted --", [req.user.id]);
promise.then(console.log, console.error);
});
I'm trying to convert this from an existing set up that doesn't use promises, so I know the connection is set up properly and the query is valid. Whenever I try to request this route, I get the same message in stderr:
[TypeError: Cannot read property 'connectionConfig' of undefined]
I don't know where it's coming from so I'm not sure how to find the full stacktrace. I also tried an alternate version of this code where I had my own function instead of console.log and console.error, but this function was never called and the same error appeared.

Updated answer:
You're probably losing the lexical scope to connection when you denodeify the query method.
Looking at the Q documentation it says this can be an issue:
If you are working with methods, instead of simple functions, you can easily run in to the usual problems where passing a method to another function—like Q.nfcall—"un-binds" the method from its owner.
To fix this try using Q.nbind instead:
var query = Q.nbind(connection.query, connection);
var promise = query("-- query ommitted --", [req.user.id]);
promise.then(console.log, console.error);
Original answer:
Looking at the node-mysql source, the only place connectionConfig is accessed is in Pool.js. So my guess would be that you've got an issue with how the pool is being configured.

Related

How to pass data in a promise chain, I am using sequelize

I am really struggling here. Admittedly I am no guru especially when it comes to node and asynchronous programming, I am an old C# .net developer so I am comfortable with code but struggling here.
Here's the back story, short and sweet. I have a pg database and I am using the sequelize ORM tools to create a relatively simple CRUD app.
Here's what I want to do.
Make a call to the findAll function on one object.
I need a piece of information from that first call so that I can make a subsequent call.
For instance. Lookup the current user to get their details, grab their ID and now lookup their display preferences.
I know I can run two requests that are not linked using Promise.all, here is an example of this already working.
var delConfig = deliverabiltyConfigs.findAll2(req.signedCookies.tsUser);
var delPack = deliverabilityPackages.findAll2();
Promise.all([delConfig, delPack]).then((results) =>{
res.render('index', { title: 'Deliverability Calculator', UserEmail : req.signedCookies.tsUser, UserName : req.signedCookies.tsUserName, data:results[0], packs:results[1]});
});
Where I am stuck is passing data from one promise to then next and needing them to run asynchronously.
Please help!
There are a few way you can do this. Either use promise chaining or with async & await.
Promise chaining might be the simplest way to do this now, but I would suggest using async await as its easier to read. Since you didn't really provide a sample of what you were trying to do I will make something generic that should hopefully help.
So using promise chaining you would do something like:
pgConnection.findAll().then((data) => {
const foo = data.foo;
pgConnection.findSomething(foo).then((data2) => {
console.log(data2);
});
});
What is happening here is once the promise from findAll() is resolved successfully it will call the .then method and will pass the resulting data there for you to use in your next db query and then I am just printing out the result of the final db query.
This is how you could do it using async & await:
async function getFoo() {
const data = await pgConnection.findAll();
const foo = data.foo;
const data2 = await pgConnection.findSomething(foo);
console.log(data2);
}
The await keyword can only be used inside of an async function so it might not be as simple to change as just using a .then promise chain.

Node.js: mongoose.once('open') doesn't execute callback function

I'm trying to save some json files inside my database using a custom function I've wrote. To achieve that I must connect to the database which I'm trying to do using this piece of code at the start of the function:
let url = "mongodb://localhost:27017/database";
(async () => {
const directory = await fs.promises.readdir(__dirname + '/files')
let database = await mongoose.createConnection(url, {useNewUrlParser:true, useUnifiedTopology:true});
database.on('error', error => {
throw console.log("Couldn't Connect To The Database");
});
database.once('open', function() {
//Saving the data using Schema and save();
Weirdly enough, when executing database.once('open', function()) the callback function isn't being called at all and the program just skips the whole saving part and gets right to the end of the function.
I've searched the web for a solution, and one solution suggested to use mongoose.createConnection instant of mongoose.connect.
As you can see it didn't really fixed the issue and the callback function is still not being called.
How can I fix it, and why it happens?
Thanks!
mongoose.createConnection creates a connection instance and allows you to manage multiple db connections as the documentation states. In your case using connect() should be sufficient (connect will create one default connection which is accessible under mongoose.connection).
By awaiting the connect-promise you don't actually need to listen for the open event, you can simply do:
...
await mongoose.connect(url, {useNewUrlParser:true, useUnifiedTopology:true});
mongoose.model('YourModel', YourModelSchema);
...

Getting a value from a Node.js callback

I'm trying to get my head around callbacks in Node.JS and it's pretty foreign compared to what I'm used to.
I have the following example from another post on here:
var someOutput;
var myCallback = function(data) {
console.log('got data: '+data);
someOutput = data;
};
var usingItNow = function(callback) {
callback('get it?');
};
//now do something with someOutput outside of the functions
I have added the someOutput variable - I want to get the text 'get it?' (obviously I don't) into there so that I can concatenate it on to a string, but it's not working in any combination I've tried.
I must be missing something fundamental here!
Thank you for the help.
You should call the function:
usingItNow(myCallback);
But anyway it is not a good practice to use callback to set variable and consume later. It will work for you now, but later if callback will be async, it will fail.
Consider using Promise and use someOutput in the then function.
A good Promise package is Bluebird
If you want to do it like a pro, consider using Promise.coroutine
http://bluebirdjs.com/docs/api/promise.coroutine.html
Or async + await if you are using an updated version of Node.js
Look on http://node.green/#ES2017-features-async-functions to check what avilable on your node version
As commented by emil:
"call usingItNow(myCallback);"
doh!

how to use mongo db.eval through Mongoose

From my mongo shell I can run functions with db.eval like:
db.eval('return 7;');
And, but for a deprecation warning, the parameter function is run properly.
Now I want to call such a 'script' from node.js, through mongoose.
I've tried to just call db.eval with the stringified function code as parameter (as in here):
mongoose.connect(PATH_TO_A_MONGO_DATABASE);
mongoose.connection.db.eval('return 9;', function(err, result){
console.log(result);
//etc.
});
This silently ignores the callback. No error is thrown, and the callback function is never called.
When doing this, I checked that mongoose.connection.db.eval is actually a function.
Since db.eval also has a Promise interface, also tried:
mongoose.connection.db.eval('return 5;').then(console.log).catch(console.log);
With the same result: no errors, just silence.
So, I guess I'm missing something with the syntax, but I can't find documentation or examples about this. Any similar questions like this or this didn't help.
PD1: I'm willing to do this because I need to call a procedure stored in system.js through mongoose. I can't do that too. However, I can't even run a silly script like return 5;, so I'm asking for the simpler task before. Any advice on how to call server scripts with mongoose is welcome.
PD2: I'm aware stored server scripts in mongo are a bad practice, and that they are deprecated for a reason and so on... but I can't just decide about that. I've been told to do that at my company, and the co-worker who set up the original code of the stored server script is not here now.
Ok, I figured out why my db.eval callbacks was being ignored. It is related with the mongoose connection.
If you start a connection like:
const conn = mongoose.connect(PATH_TO_DB);
And then just make a query:
conn.model(a_collection, a_schema).find({}).exec().then()...
Even if you just call the query right after the connection -it is, logically, an asynchronous process-, mongooose figures that it has to wait to the connection to be in a proper state, then fire the query, then call the callback with the query results.
However, this doesn't work the same way with db.eval(). just trying to call db.eval() right after the call to the connection, the callback is silently ignored:
const conn = mongoose.connect(PATH_TO_DB);
conn.db.eval('return 5;', (err, response) => {
//nothing happends
})
That was the way I was creating the connection and calling db.eval, so I couldn't get db.eval() to work.
In order to fire a db.eval and make it work, it seems that you need to wait for the connection explicitly:
const conn = mongoose.connect(PATH_TO_DB, err => {
mongoose.connection.db.eval('return 5', (err, result) => {
result; //5!
})
});
To make a query before any attemps to call db.eval also works:
const conn = mongoose.connect(PATH_TO_DB);
conn.model(a_collection, a_schema).find({}).exec()
.then(() => {
conn.db.eval('return 5', (err, result) => {
result; //5!
})
})

Bluebird, node-mysql, pooling, and disposing

Currently trying to implement a different approach to connecting to my database using promises and pooling. This is what I have as of the moment:
// databaseConnection.js
var configDB = require('./database.js');
var mysql = require('promise-mysql');
var pool = mysql.createPool(configDB.connectionData);
function getSqlConnection() {
return pool.getConnection(configDB.connectionData).disposer(function(connection) {
connection.release();
});
}
module.exports = getSqlConnection;
Then I use the query like this:
#sqlQuery.js
var Promise = require("bluebird");
var getSqlConnection = require('./databaseConnection')
Promise.using(getSqlConnection(), function(connection) {
return connection.query("SELECT * FROM EXAMPLE_TABLE").then(function(row) {
return process(rows);
}
}
I'm using this library which is just node-mysql wrapped with BlueBird promises. With that, I wanted to take advantage of BlueBird's disposing and using capability so I would only be connected to the DB when I needed to be.
Currently though I'm getting an error from Connection.js of mysql stating: cb is not a function. Based on this question I have somewhat of an idea of what I'm doing wrong but I'm not sure how I would go about using that with BlueBird's dispose/using paradigm. Thanks in advance for anyone that can help!
Huge lack of oversight on my part. The following line:
return pool.getConnection(configDB.connectionData).disposer...
should be:
return pool.getConnection().disposer...
Sorry about that. Still getting an error for connection.release not being a function which is strange but at least I can move forward with debugging that.

Resources