Skip to content

Commit 2fd9c77

Browse files
authored
Make Query & NativeQuery implement the promise interface (brianc#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
1 parent 9b1d16d commit 2fd9c77

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

lib/native/query.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ var NativeQuery = module.exports = function(native) {
2626

2727
util.inherits(NativeQuery, EventEmitter);
2828

29+
NativeQuery.prototype.then = function(callback) {
30+
return this.promise().then(callback);
31+
};
32+
33+
NativeQuery.prototype.catch = function(callback) {
34+
return this.promise().catch(callback);
35+
};
36+
37+
NativeQuery.prototype.promise = function() {
38+
if (this._promise) return this._promise;
39+
this._promise = new Promise(function(resolve, reject) {
40+
this.once('end', resolve);
41+
this.once('error', reject);
42+
}.bind(this));
43+
return this._promise;
44+
};
45+
2946
NativeQuery.prototype.handleError = function(err) {
3047
var self = this;
3148
//copy pq error fields into the error object

lib/query.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,29 @@ var Query = function(config, values, callback) {
2626
this._result = new Result(config.rowMode, config.types);
2727
this.isPreparedStatement = false;
2828
this._canceledDueToError = false;
29+
this._promise = null;
2930
EventEmitter.call(this);
3031
};
3132

3233
util.inherits(Query, EventEmitter);
3334

35+
Query.prototype.then = function(callback) {
36+
return this.promise().then(callback);
37+
};
38+
39+
Query.prototype.catch = function(callback) {
40+
return this.promise().catch(callback);
41+
};
42+
43+
Query.prototype.promise = function() {
44+
if (this._promise) return this._promise;
45+
this._promise = new Promise(function(resolve, reject) {
46+
this.once('end', resolve);
47+
this.once('error', reject);
48+
}.bind(this));
49+
return this._promise;
50+
};
51+
3452
Query.prototype.requiresPreparation = function() {
3553
//named queries must always be prepared
3654
if(this.name) { return true; }
@@ -52,14 +70,13 @@ Query.prototype.requiresPreparation = function() {
5270
//metadata used when parsing row results
5371
Query.prototype.handleRowDescription = function(msg) {
5472
this._result.addFields(msg.fields);
73+
this._accumulateRows = this.callback || !this.listeners('row').length;
5574
};
5675

5776
Query.prototype.handleDataRow = function(msg) {
5877
var row = this._result.parseRow(msg.fields);
5978
this.emit('row', row, this._result);
60-
61-
//if there is a callback collect rows
62-
if(this.callback) {
79+
if (this._accumulateRows) {
6380
this._result.addRow(row);
6481
}
6582
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var helper = require(__dirname + '/../test-helper');
2+
var pg = helper.pg;
3+
var semver = require('semver')
4+
5+
if (semver.lt(process.version, '0.12.0')) {
6+
return console.log('promises are not supported in node < v0.10')
7+
}
8+
9+
process.on('unhandledRejection', function(e) {
10+
console.error(e, e.stack)
11+
process.exit(1)
12+
})
13+
14+
pg.connect(helper.config, assert.success(function(client, done) {
15+
client.query('SELECT $1::text as name', ['foo'])
16+
.then(function(result) {
17+
assert.equal(result.rows[0].name, 'foo')
18+
return client
19+
})
20+
.then(function(client) {
21+
client.query('ALKJSDF')
22+
.catch(function(e) {
23+
assert(e instanceof Error)
24+
})
25+
})
26+
27+
client.query('SELECT 1 as num')
28+
.then(function(result) {
29+
assert.equal(result.rows[0].num, 1)
30+
done()
31+
pg.end()
32+
})
33+
}))

test/integration/client/type-coercion-tests.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,14 @@ helper.pg.connect(helper.config, assert.calls(function(err, client, done) {
202202
if(!helper.config.binary) {
203203
test("postgres date type", function() {
204204
var client = helper.client();
205-
var testDate = new Date (2010, 9, 31);
205+
var testDate = new Date(2010, 9, 31);
206206
client.on('error', function(err) {
207207
console.log(err);
208208
client.end();
209209
});
210210
client.query("SELECT $1::date", [testDate], assert.calls(function(err, result){
211211
assert.isNull(err);
212-
assert.strictEqual(result.rows[0].date.toString(), testDate.toString());
212+
assert.strictEqual(result.rows[0].date.toString(), new Date(Date.UTC(2010, 9, 31)).toString());
213213
}));
214214
client.on('drain', client.end.bind(client));
215215
});

0 commit comments

Comments
 (0)