story
I'm thinking of something like the below as a dbHelper class.
Note I'm passing the error messages into the deferred reject method rather than using console logging. I'm not sure if the q API supports that as you don't, but if it doesn't that seems like a bit of an odd design decision by the library authors, how else are you supposed to pass errors back? Unless I'm misunderstanding promises. If you want to have console logging of failed defers I would recommend either editing the source of Q or monkey patching the reject method to do it automatically.
It's also worth noting I am deliberately not checking rows length, etc. You should let exceptions do what they're supposed to do as something very serious has gone wrong if rows.length == 0 or rows[0] is null or rows[0]['count'] doesn't exist. A SELECT COUNT should always return 1 row and if you've named the column it should definitely be there.
//this is totally untested code to show the idea of
//how you should abstract the boilerplate from your code
var dbHelper = function() {
var db = require('./db'),
Q = require('q');
var dbHelperInner = {
query : function(query, onComplete) {
var dfd = Q.defer();
try {
var cmd = new DbCommand(dfd);
cmd.execute(query, onComplete);
} catch(e) {
dfd.reject(e);
}
return dfd.promise;
}
}
function DbCommand(dfd) {
if (!db.canRead()) {
throw "db unavailable";
}
this.dfd = dfd;
}
DbCommand.prototype.execute = function(query, onComplete) {
var self = this;
dbConnectionPool.acquire(function(acquireError, connection) {
if (acquireError) {
self.dfd.reject(acquireError);
return;
}
connection.query(query, function(queryError, rows) {
if (queryError) {
self.dfd.reject(queryError);
} else {
try {
self.dfd.resolve(
onComplete(rows));
} catch (e) {
self.dfd.reject(e);
}
}
dbConnectionPool.release(connection);
});
});
}
return dbHelperInner;
}();
//and then you could use it like this
//which is almost identical to the code I posited above
function playlistCount(){
return dbHelper.query('SELECT COUNT(id) AS count FROM Playlists;', function(rows) {
return parseInt(rows[0]['count']);
});
}