Make Query & NativeQuery implement the promise interface (#1047)

* Make Query & NativeQuery implement the promise interface

* Fix test

* Use older node API for checking listener length

* Do not test for promises on node@v0.10.0
This commit is contained in:
Brian C 2016-06-10 17:18:19 -05:00 committed by GitHub
parent 9b1d16dfd2
commit 2fd9c77085
4 changed files with 72 additions and 5 deletions

View File

@ -26,6 +26,23 @@ var NativeQuery = module.exports = function(native) {
util.inherits(NativeQuery, EventEmitter);
NativeQuery.prototype.then = function(callback) {
return this.promise().then(callback);
};
NativeQuery.prototype.catch = function(callback) {
return this.promise().catch(callback);
};
NativeQuery.prototype.promise = function() {
if (this._promise) return this._promise;
this._promise = new Promise(function(resolve, reject) {
this.once('end', resolve);
this.once('error', reject);
}.bind(this));
return this._promise;
};
NativeQuery.prototype.handleError = function(err) {
var self = this;
//copy pq error fields into the error object

View File

@ -26,11 +26,29 @@ var Query = function(config, values, callback) {
this._result = new Result(config.rowMode, config.types);
this.isPreparedStatement = false;
this._canceledDueToError = false;
this._promise = null;
EventEmitter.call(this);
};
util.inherits(Query, EventEmitter);
Query.prototype.then = function(callback) {
return this.promise().then(callback);
};
Query.prototype.catch = function(callback) {
return this.promise().catch(callback);
};
Query.prototype.promise = function() {
if (this._promise) return this._promise;
this._promise = new Promise(function(resolve, reject) {
this.once('end', resolve);
this.once('error', reject);
}.bind(this));
return this._promise;
};
Query.prototype.requiresPreparation = function() {
//named queries must always be prepared
if(this.name) { return true; }
@ -52,14 +70,13 @@ Query.prototype.requiresPreparation = function() {
//metadata used when parsing row results
Query.prototype.handleRowDescription = function(msg) {
this._result.addFields(msg.fields);
this._accumulateRows = this.callback || !this.listeners('row').length;
};
Query.prototype.handleDataRow = function(msg) {
var row = this._result.parseRow(msg.fields);
this.emit('row', row, this._result);
//if there is a callback collect rows
if(this.callback) {
if (this._accumulateRows) {
this._result.addRow(row);
}
};

View File

@ -0,0 +1,33 @@
var helper = require(__dirname + '/../test-helper');
var pg = helper.pg;
var semver = require('semver')
if (semver.lt(process.version, '0.12.0')) {
return console.log('promises are not supported in node < v0.10')
}
process.on('unhandledRejection', function(e) {
console.error(e, e.stack)
process.exit(1)
})
pg.connect(helper.config, assert.success(function(client, done) {
client.query('SELECT $1::text as name', ['foo'])
.then(function(result) {
assert.equal(result.rows[0].name, 'foo')
return client
})
.then(function(client) {
client.query('ALKJSDF')
.catch(function(e) {
assert(e instanceof Error)
})
})
client.query('SELECT 1 as num')
.then(function(result) {
assert.equal(result.rows[0].num, 1)
done()
pg.end()
})
}))

View File

@ -202,14 +202,14 @@ helper.pg.connect(helper.config, assert.calls(function(err, client, done) {
if(!helper.config.binary) {
test("postgres date type", function() {
var client = helper.client();
var testDate = new Date (2010, 9, 31);
var testDate = new Date(2010, 9, 31);
client.on('error', function(err) {
console.log(err);
client.end();
});
client.query("SELECT $1::date", [testDate], assert.calls(function(err, result){
assert.isNull(err);
assert.strictEqual(result.rows[0].date.toString(), testDate.toString());
assert.strictEqual(result.rows[0].date.toString(), new Date(Date.UTC(2010, 9, 31)).toString());
}));
client.on('drain', client.end.bind(client));
});