andrsnn andrsnn - 7 months ago 64
Javascript Question

Q promise .then() undefined

I am attempting to asynchronously pull data from a MySQL database then process the results with Q promise (first attempt ever). I am using the Q defer() function listed here. I have created a "wrapper" object I will eventually attach to req.db or access via circular dependency from com.db (how it is currently used) to allow for an api use in my app.

Node throws an error pointing at the .then callback:

this.go().then(function(stuff){
^
TypeError: Cannot call method 'then' of undefined


I have tried the following:

var com = require('./mainRebuild');

function Base() {
this.results = [];
this.query = 'query here';
this.go = function() {

com.pool.getConnection(function(err, con) {

if (err) throw err;
/*
THIS WORKS FINE (with callbacks)
con.query('SELECT * FROM Users', function(err, rows){
if (err) throw err;
if (rows){

for (var i = 0; i < rows.length; i++){
this.results.push(rows[i]);
//console.log(rows[i]);
}
}
con.release();
return this.results;
}.bind(this));

*/
var defer = com.Q.defer();
con.query('SELECT * FROM Users', defer.makeNodeResolver());
return defer.promise();
}.bind(this));
}
}

function DB() {
this.getAllUsers = function() {
this.query = 'SELECT * FROM Users';
this.go().then(function(stuff) {
console.log(stuff);
}, function(err) {
console.log(err);
});
}

}

DB.prototype = new Base();

module.exports = DB;


The com object exists in the main app, it holds all the common require modules.

I also tried (seems far more wrong):

this.deffered = com.Q.defer();
com.pool.getConnection(function(err, con) {

if (err) this.deferred.reject(new Error(err));

con.query('SELECT * FROM Users', function(err, rows) {
if (err) throw err;
if (rows) {
this.deferred.resolve(rows);
}
con.release();
return this.deferred.promise.done;
}.bind(this));

com.Q.nfcall(this.go()).then...


I have found several articles on adapting Q to node like this.

Answer

Something like this should do it ("should", because I have no way to test it with MySQL)

var Q = require('Q');

function DB(pool) {
    this.asyncQuery = function(sql) {
        return function () { 
            var result = Q.defer(),
                paramsArray = [].slice.call(arguments);
            pool.getConnection(function(err, con) {
                result.promise.finally(function () {
                    con.release();
                });
                if (err) return result.thenReject(err);
                con.query(sql, paramsArray, result.makeNodeResolver());
            });
            return result.promise;
        };
    };
    this.getAllUsers = this.asyncQuery('SELECT * FROM Users');
    this.getUserByName = this.asyncQuery('SELECT * FROM Users WHERE name = ?');
}

module.exports = DB;

Usage:

var DB = require('./DB');
var com = require('./mainRebuild');
var db = new DB(com.pool);

db.getAllUsers().then(function (users) {
    console.log(users);
});

db.getUserByName('JohnDoe').then(function (user) {
    console.log(user);
});

var customQuery = db.asyncQuery('SELECT * FROM foo WHERE id = ?');
customQuery(42).then(function (result) {
    console.log(result);
});
Comments