Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
818 views
in Technique[技术] by (71.8m points)

node.js - nodejs sqlite3 db.run as a bluebird promise

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
            }
        }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
        }
    })

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...