Search code examples
node.jsnode-sqlite3

Struggling with querying database due to node being asynchronous


This is my first project with Node.js, as well as with sqlite3. As node is asynchronous, I am really struggling, as I have a .js file specifically for functions that interact with my database. But this means that whenever I try to call these functions and assign them to a variable, the things I try and do to with the variable run before I can assign. For example:

//From my .js file that handles server stuff
app.post('/login', function (req, res, next) {
    placeholder = loginVer("Test", "Test")
    console.log(placeholder) //Outputs pending promise
})

//From my database.js file
function databaseUserQuery(email){
    return new Promise(function (resolve,reject) {
        info = [] //empty array, if query can't find anything, info stays null which serves the purpose
        db.each("SELECT Email emailS, Password pword FROM Users WHERE Email  = ?", [email], (err, row) => {
            info[0] = row.emailS;
            info[1] = row.pword;
            resolve(info);
        })
        setTimeout(() => {
            resolve(info);
        },10)
    })
}

async function loginVer(email, password) {
    await databaseUserQuery(email).then(function(result) {
        if(result[0] == email){ //Checks if user exists (via email)
            if(result[1] == password){return(0)} //returns 0 if password matches
            else{return(1)} //Returns 1 if password is wrong but user exists
        } else {return(2)} //Returns 2 if user does not exist
    })
}

I'm sorry if the code itself isn't good, but I've used promises to make sure that when the loginVer function is called, it does a query first and then procedes to work on the output but I really think/hope there is a better way of doing this.


Solution

  • //changed handler to async function
    app.post('/login', async function (req, res, next) {
        try {
            //you can use await here now
            let placeholder = await loginVer("Test", "Test")
            console.log(placeholder) //Outputs pending promise
        } catch (error) {
            //any error with throw or reject statement in underlying function calls will propagate here
            console.log(error)
        }
    })
    
    //From my database.js file
    function databaseUserQuery(email) {
        return new Promise(function (resolve, reject) {
            info = [] //empty array, if query can't find anything, info stays null which serves the purpose
            db.each("SELECT Email emailS, Password pword FROM Users WHERE Email  = ?", [email], (err, row) => {
                if (err) {
                    return reject(err)
                }
                info[0] = row.emailS;
                info[1] = row.pword;
                resolve(info);
            })
        })
    }
    
    async function loginVer(email, password) {
        //either user async await or use promise chaining. databaseUserQuery returns promise so we can use await here
        let result = await databaseUserQuery(email)
        if (result[0] == email) { //Checks if user exists (via email)
            if (result[1] == password) { return (0) } //returns 0 if password matches
            else { return (1) } //Returns 1 if password is wrong but user exists
        } else { return (2) } //Returns 2 if user does not exist
    }
    
    • async/await and then/catch interchangeable.
    • if a function returns a promise you can use it either async/await way or then/catch way.await databaseUserQuery(email).then(function(result) { in this statement you are mixing both.
    • always catch errors with try/catch or .catch. so it will be easier to debug the issue.