Skip to content
This repository was archived by the owner on Dec 30, 2019. It is now read-only.

Commit 0a838ff

Browse files
committed
Don’t create promises when callbacks are provided
It’s incorrect to do so. One consequence is that a rejected promise will be unhandled, which is currently annoying, but also dangerous in the future: > DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. The way callbacks are used currently also causes #24 (hiding of errors thrown synchronously from the callback). One fix for that would be to call them asynchronously from inside the `new Promise()` executor: process.nextTick(cb, error); I don’t think it’s worth implementing, though, since it would still be backwards-incompatible – just less obvious about it. Also fixes a bug where the `Pool.prototype.connect` callback would be called twice if there was an error.
1 parent c868226 commit 0a838ff

2 files changed

Lines changed: 57 additions & 18 deletions

File tree

index.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,28 @@ var Pool = module.exports = function (options, Client) {
2222

2323
util.inherits(Pool, EventEmitter)
2424

25+
Pool.prototype._promise = function (cb, executor) {
26+
if (!cb) {
27+
return new this.Promise(executor)
28+
}
29+
30+
function resolved (value) {
31+
process.nextTick(cb, null, value)
32+
}
33+
34+
function rejected (error) {
35+
process.nextTick(cb, error)
36+
}
37+
38+
executor(resolved, rejected)
39+
}
40+
41+
Pool.prototype._promiseNoCallback = function (callback, executor) {
42+
return callback
43+
? executor()
44+
: new this.Promise(executor)
45+
}
46+
2547
Pool.prototype._destroy = function (client) {
2648
if (client._destroying) return
2749
client._destroying = true
@@ -52,15 +74,17 @@ Pool.prototype._create = function (cb) {
5274
}
5375

5476
Pool.prototype.connect = function (cb) {
55-
return new this.Promise(function (resolve, reject) {
77+
return this._promiseNoCallback(cb, function (resolve, reject) {
5678
this.log('acquire client begin')
5779
this.pool.acquire(function (err, client) {
5880
if (err) {
5981
this.log('acquire client. error:', err)
6082
if (cb) {
6183
cb(err, null, function () {})
84+
} else {
85+
reject(err)
6286
}
63-
return reject(err)
87+
return
6488
}
6589

6690
this.log('acquire client')
@@ -79,9 +103,9 @@ Pool.prototype.connect = function (cb) {
79103

80104
if (cb) {
81105
cb(null, client, client.release)
106+
} else {
107+
resolve(client)
82108
}
83-
84-
return resolve(client)
85109
}.bind(this))
86110
}.bind(this))
87111
}
@@ -94,36 +118,25 @@ Pool.prototype.query = function (text, values, cb) {
94118
values = undefined
95119
}
96120

97-
return new this.Promise(function (resolve, reject) {
121+
return this._promise(cb, function (resolve, reject) {
98122
this.connect(function (err, client, done) {
99123
if (err) {
100-
if (cb) {
101-
cb(err)
102-
}
103124
return reject(err)
104125
}
105126
client.query(text, values, function (err, res) {
106127
done(err)
107128
err ? reject(err) : resolve(res)
108-
if (cb) {
109-
cb(err, res)
110-
}
111129
})
112130
})
113131
}.bind(this))
114132
}
115133

116134
Pool.prototype.end = function (cb) {
117135
this.log('draining pool')
118-
return new this.Promise(function (resolve, reject) {
136+
return this._promise(cb, function (resolve, reject) {
119137
this.pool.drain(function () {
120138
this.log('pool drained, calling destroy all now')
121-
this.pool.destroyAllNow(function () {
122-
if (cb) {
123-
cb()
124-
}
125-
resolve()
126-
})
139+
this.pool.destroyAllNow(resolve)
127140
}.bind(this))
128141
}.bind(this))
129142
}

test/index.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,32 @@ describe('pool', function () {
103103
pool.end(done)
104104
})
105105
})
106+
107+
it('does not create promises when connecting', function (done) {
108+
var pool = new Pool()
109+
var returnValue = pool.connect(function (err, client, release) {
110+
release()
111+
if (err) return done(err)
112+
pool.end(done)
113+
})
114+
expect(returnValue).to.be(undefined)
115+
})
116+
117+
it('does not create promises when querying', function (done) {
118+
var pool = new Pool()
119+
var returnValue = pool.query('SELECT 1 as num', function (err) {
120+
pool.end(function () {
121+
done(err)
122+
})
123+
})
124+
expect(returnValue).to.be(undefined)
125+
})
126+
127+
it('does not create promises when ending', function (done) {
128+
var pool = new Pool()
129+
var returnValue = pool.end(done)
130+
expect(returnValue).to.be(undefined)
131+
})
106132
})
107133

108134
describe('with promises', function () {

0 commit comments

Comments
 (0)