I'm attempting to use sqlite3 in a express app. Basically, I get a rest request, based on the rest request, I query an external REST request. Between the response from the external request & the data passed in from the original REST request, I then do an update or insert into one of my sqlite3 tables.
The problem I'm running into, is that in db.run(sqlStatement, paramArray, function(err))
, the function(err) is a callback where err
is either an error, or a nil
. In addition to that, IF the err
param is null
, then the this
reference contains 2 properties, one of which tells me the number of rows modified by the statement. (https://github.com/mapbox/node-sqlite3/wiki/API#databaserunsql-param--callback for reference)
Thing is, I run bluebird's promisifyAll
on the sqlite3 module, and then use the resultant
db.runAsync(sqlStatement, paramArray).then(err) {
console.log(this) //results in a null
}
So I'm unable to actually figure out whether anything was updated.
My entire section of code looks a little like this:
function handleRequest(req, res) {
//this returns the response as the first object
request.getAsync('http://www.example.com', reqObj)
.then(prepareDbObjects) //prepares an array of objects to update the DB with
.then(attemptUpdate)
.then(function(rowsUpdated) {
res.json(rowsUpdated)
}
}
function attemptUpdate(updateObjs) {
var promiseMap = Promise.map(updateObjs, function(singleObj) {
return updateOrInsertObj(singleObj)
}
return promiseMap
}
function updateOrInsertObj(singleObj) {
return db.runAsync(sqlStatement, singleObj)
.then(function(err) {
if(err) {
//handle error
} else {
console.log("this should be an object with 2 properties", this)
//but instead it is null
}
}
}
I went looking in the node-sqlite3
code, and I'm pretty sure the way it returns this
in the successful callback function, rather than as an actual param, is the problem. Which means even attempting to use bluebird's multiArgs=true
parameter didn't work since there wasn't a proper return value.
So I attempted to wrap the db.run function in my own custom promise method, and that seemed to do the trick.
Specifically, I did:
function runCustomAsync(sql, params) {
return new Promise(function(resolve, reject) {
db.run(sql, params, function cb(err) {
if(err) {
var responseObj = {
'error': err
}
reject(responseObj);
} else {
var responseObj = {
'statement': this
}
resolve(responseObj);
}
});
});
}
db.runCustomAsync = runCustomAsync;
module.exports = db;
It IS a little different from how it's normally handled. I'm now returning an object that may contain either the this
object, or it might contain the err
object.
In my original request, I now do
db.runCustomAsync(sqlStatement, params)
.then(function(dbResponseObj) {
if(dbResponseObj.error) {
//handle error
} else {
//do stuff with dbResponseObj.statement
}
})