I have a database module which handles connection setup and pooling, and a query module that relies on the database module to execute queries. I'm adapting both of them to use Promises for asynchronous calls. So far, I've adapted the query module - now I wish to convert the database module.
Here's the problem: the database module should be usable both directly and implicitly by the query module (which currently relies on callbacks). How can I use promises in both modules' methods without turning this into a maze of twisty little passages?
Here's what I've done so far:
Database Module
getConnection: function(callback) { //this should return a promise
this.pool.getConnection(function(error, connection){
callback(error, connection);
});
},
Query Module this should then
on the getConnection
promise, execute query, and then reject/resolve for it's caller
request: function(queryRequest) {
return new Promise(function(resolve, reject){
Database.getConnection(function(error, connection){
if(error) {
reject({error: error, queryRequest: queryRequest});
} else {
connection.query(queryRequest.sql, queryRequest.values, function(error, rows, fields){
if(error) {
reject({error: error, queryRequest: queryRequest});
} else {
resolve({rows: rows, fields: fields, queryRequest: queryRequest});
}
connection.release()
});
}
});
});
},
getConnection
should return a promise [for the connection]
Rather not, it should use the disposer pattern instead, and call connection.release()
itself:
function withConnection(callback) {
var pool = this.pool;
var conn = new Promise(function(resolve, reject) {
pool.getConnection(function(error, connection){
if (error)
reject(error);
else
resolve(connection);
});
});
return conn.then(function(connection) {
var res = conn.then(callback); // safe call
return res.then(fin); // `finally` shim
function fin() {
connection.release();
return res;
}
});
}
function request(queryRequest) {
return Database.withConnection(function(connection) {
return new Promise(function(resolve, reject) {
connection.query(queryRequest.sql, queryRequest.values, function(error, rows, fields) {
if (error)
reject(error);
else
resolve({rows: rows, fields: fields, queryRequest: queryRequest});
});
});
}).catch(function(error) {
error.queryRequest = queryRequest;
throw error;
});
}
Database Module
getConnection: function() {
return new Promise(function(resolve, reject) {
this.pool.getConnection(function(error, connection){
if(error) {
reject(error);
} else {
resolve(connection);
}
});
});
},
Query Module
execute: function(queryRequest) {
var self = this;
this.queryRequest = queryRequest;
return new Promise(function(resolve, reject) {
self.resolve = resolve;
self.reject = reject;
var promise = Database.getConnection();
promise.then(self.result.bind(self), self.fault.bind(self));
});
},
result: function(connection) {
var self = this;
connection.query(this.queryRequest.sql, this.queryRequest.values, function(error, rows, fields) {
if (error) {
self.reject(error);
} else {
self.resolve({rows: rows, fields: fields, queryRequest: self.queryRequest});
}
connection.release();
});
},
fault: function(info) {
self.reject(info);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.