The issue with your code
The problem with the above approach is that if you forget releasing the connection after every single time you perform getDb
you have a resource leak that might freeze your app eventually when it runs out of the resource you're leaking.
You might, in one place do:
var users = getDb().then(function(conn){
return conn.query("SELECT name FROM users");
});
Which will leak a database connection that was never closed.
The disposer pattern
The disposer pattern is a way to couple a scope of code with owning the resource. By binding the resource to a scope we make sure it is always released when we're done with it and we can't easily forget to release it. It is similar to using
in C#, with
in Python and try-with-resource in Java as well as RAII in C++.
It looks like:
withResource(function(resource){
return fnThatDoesWorkWithResource(resource); // returns a promise
}).then(function(result){
// resource disposed here
});
Applying it here
If we wrote our code as:
function withDb(work){
var _db;
return myDbDriver.getConnection().then(function(db){
_db = db; // keep reference
return work(db); // perform work on db
}).finally(function(){
if (_db)
_db.release();
});
}
We could write our above code as:
withDb(function(conn){
return conn.query("SELECT name FROM users");
}).then(function(users){
// connection released here
});
Examples of users of the disposer pattern are sequelize and knex (bookshelf's query builder). It's also possible to use it for simpler things like hiding a loader when all AJAX requests completed for instance.
Bluebird
Since you're using bluebird, it has dedicated Promise.using
and .disposer
functions built in that let you handle taking/releasing multiple resources at once you might want to consider.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…